Comparing version 5.2.0 to 6.0.0
@@ -0,1 +1,18 @@ | ||
## 6.0.0 (12/02/20) | ||
* Add support for setting an example value via the `example(string)` function. | ||
* Passing default values is now performed using the `default(string)` function. | ||
* Defer checks for `required()` until an accessor such as `asString()` is invoked. | ||
* Fix typings issue where `required()` was undefined on a `IPresentVariable`. | ||
Migration from 5.x to 6.0.0 should be smooth. Change any instance of | ||
`env.get(target, default)` to `env.get(target).default(default)`. For example: | ||
```js | ||
// Old 5.x code | ||
const emailAddr = env.get('EMAIL_ADDR', 'admin@example.com').asString() | ||
// New 6.x compatible code | ||
const emailAddr = env.get('EMAIL_ADDR').default('admin@example.com').asString() | ||
``` | ||
## 5.2.0 (22/11/19) | ||
@@ -2,0 +19,0 @@ * The `required()` function now verifies the variable is not an empty string |
@@ -13,2 +13,20 @@ | ||
/** | ||
* Provide an example value that can be used in error output if the variable | ||
* is not set, or is set to an invalid value | ||
*/ | ||
example: (example: string) => IPresentVariable | ||
/** | ||
* Set a default value for this variable. This will be used if a value is not | ||
* set in the process environment | ||
*/ | ||
default: (value: string) => IPresentVariable; | ||
/** | ||
* Ensures the variable is set on process.env. If it's not set an exception | ||
* will be thrown. Can pass false to bypass the check. | ||
*/ | ||
required: (isRequired?: boolean) => IPresentVariable; | ||
/** | ||
* Converts a number to an integer and verifies it's in port ranges 0-65535 | ||
@@ -108,8 +126,20 @@ */ | ||
/** | ||
* Converts a bas64 environment variable to ut8 | ||
* Decodes a base64-encoded environment variable | ||
*/ | ||
convertFromBase64: () => IOptionalVariable | ||
convertFromBase64: () => IOptionalVariable; | ||
/** | ||
* Ensures the variable is set on process.env, if not an exception will be thrown. | ||
* Provide an example value that can be used in error output if the variable | ||
* is not set, or is set to an invalid value | ||
*/ | ||
example: (value: string) => IOptionalVariable; | ||
/** | ||
* Set a default value for this variable. This will be used if a value is not | ||
* set in the process environment | ||
*/ | ||
default: (value: string) => IPresentVariable; | ||
/** | ||
* Ensures the variable is set on process.env. If it's not set an exception will be thrown. | ||
* Can pass false to bypass the check | ||
@@ -226,7 +256,2 @@ */ | ||
/** | ||
* Gets an environment variable, using the default value if it is not already set | ||
*/ | ||
get (varName: string, defaultValue: string): PresentVariable; | ||
/** | ||
* Returns a new env-var instance, where the given object is used for the environment variable mapping. | ||
@@ -255,3 +280,2 @@ * Use this when writing unit tests or in environments outside node.js. | ||
export function get(varName: string): IOptionalVariable; | ||
export function get(varName: string, defaultValue: string): IPresentVariable; | ||
export function from<T extends Extensions, K extends keyof T>(values: NodeJS.ProcessEnv, extensions?: T): IEnv< | ||
@@ -258,0 +282,0 @@ IPresentVariable & Record<K, (...args: any[]) => ReturnType<T[K]>>, |
'use strict' | ||
const variable = require('./lib/variable') | ||
const EnvVarError = require('./lib/env-error') | ||
@@ -26,6 +27,5 @@ /** | ||
* @param {String} variableName Name of the environment variable requested | ||
* @param {String} defaultValue Optional default to use as the value | ||
* @return {Object} | ||
*/ | ||
get: (variableName, defaultValue) => { | ||
get: function (variableName) { | ||
if (!variableName) { | ||
@@ -35,3 +35,7 @@ return container | ||
return variable(container, variableName, defaultValue, extraAccessors || {}) | ||
if (arguments.length > 1) { | ||
throw new EnvVarError('It looks like you passed more than one argument to env.get(). Since env-var@6.0.0 this is no longer supported. To set a default value use env.get(TARGET).default(DEFAULT)') | ||
} | ||
return variable(container, variableName, extraAccessors || {}) | ||
} | ||
@@ -38,0 +42,0 @@ } |
@@ -15,4 +15,7 @@ 'use strict' | ||
*/ | ||
module.exports = function getVariableAccessors (container, varName, defValue, extraAccessors) { | ||
module.exports = function getVariableAccessors (container, varName, extraAccessors) { | ||
let isBase64 = false | ||
let isRequired = false | ||
let defValue | ||
let example | ||
@@ -24,3 +27,13 @@ /** | ||
function raiseError (value, msg) { | ||
throw new EnvVarError(`"${varName}" ${msg}, but was "${value}"`) | ||
let errMsg = `"${varName}" ${msg}` | ||
if (value) { | ||
errMsg = `${errMsg}, but is set to "${value}"` | ||
} | ||
if (example) { | ||
errMsg = `${errMsg}. An example of a valid value would be: ${example}` | ||
} | ||
throw new EnvVarError(errMsg) | ||
} | ||
@@ -37,11 +50,19 @@ | ||
if (typeof value === 'undefined') { | ||
if (typeof defValue === 'undefined') { | ||
// Need to return since no value is available. If a value needed to | ||
// be available required() should be called, or a default passed | ||
return | ||
if (typeof defValue === 'undefined' && isRequired) { | ||
// Var is not set, nor is a default. Throw an error | ||
raiseError(undefined, 'is a required variable, but it was not set') | ||
} else if (defValue) { | ||
value = defValue | ||
} else { | ||
// return undefined since variable is not required and | ||
// there's no default value provided | ||
return undefined | ||
} | ||
} | ||
// Assign the default as the value since process.env does not contain | ||
// the desired variable | ||
value = defValue | ||
if (isRequired) { | ||
// Need to verify that required variables aren't just whitespace | ||
if (value.trim().length === 0) { | ||
raiseError(undefined, 'is a required variable, but its value was empty') | ||
} | ||
} | ||
@@ -97,2 +118,6 @@ | ||
/** | ||
* Instructs env-var to first convert the value of the variable from base64 | ||
* when reading it using a function such as asString() | ||
*/ | ||
convertFromBase64: function () { | ||
@@ -105,19 +130,43 @@ isBase64 = true | ||
/** | ||
* Set a default value for the variable | ||
* @param {String} value | ||
*/ | ||
default: function (value) { | ||
if (typeof value === 'number') { | ||
defValue = value.toString() | ||
} else if (Array.isArray(value) || (typeof value === 'object' && value !== null)) { | ||
defValue = JSON.stringify(value) | ||
} else if (typeof value !== 'string') { | ||
throw new EnvVarError('values passed to default() must be of Number, String, Array, or Object type') | ||
} else { | ||
defValue = value | ||
} | ||
return accessors | ||
}, | ||
/** | ||
* Ensures a variable is set in the given environment container. Throws an | ||
* EnvVarError if the variable is not set or a default is not provided | ||
* @param {Boolean} isRequired | ||
* @param {Boolean} required | ||
*/ | ||
required: function (isRequired) { | ||
if (isRequired === false) { | ||
return accessors | ||
required: function (required) { | ||
if (typeof required === 'undefined') { | ||
// If no value is passed assume that developer means "true" | ||
// This is to retain support legacy usage (and intuitive) | ||
isRequired = true | ||
} else { | ||
isRequired = required | ||
} | ||
if (typeof container[varName] === 'undefined' && typeof defValue === 'undefined') { | ||
throw new EnvVarError(`"${varName}" is a required variable, but it was not set`) | ||
} | ||
return accessors | ||
}, | ||
const value = typeof container[varName] === 'undefined' ? defValue : container[varName] | ||
if (value.trim().length === 0) { | ||
throw new EnvVarError(`"${varName}" is a required variable, but its value was empty`) | ||
} | ||
/** | ||
* Set an example value for this variable. If the variable value is not set | ||
* or is set to an invalid value this example will be show in error output. | ||
* @param {String} example | ||
*/ | ||
example: function (ex) { | ||
example = ex | ||
@@ -124,0 +173,0 @@ return accessors |
{ | ||
"name": "env-var", | ||
"version": "5.2.0", | ||
"version": "6.0.0", | ||
"description": "Verification, sanatization, and type coercion for environment variables in Node.js", | ||
@@ -54,10 +54,10 @@ "main": "env-var.js", | ||
"devDependencies": { | ||
"@types/node": "~12.12.0", | ||
"@types/node": "~13.7.0", | ||
"bluebird": "~3.7.0", | ||
"chai": "~4.2.0", | ||
"coveralls": "~3.0.0", | ||
"husky": "~3.1.0", | ||
"mocha": "~6.2.0", | ||
"husky": "~4.2.2", | ||
"mocha": "~7.0.1", | ||
"mocha-lcov-reporter": "~1.3.0", | ||
"nyc": "~14.1.0", | ||
"nyc": "~15.0.0", | ||
"standard": "~14.3.0", | ||
@@ -64,0 +64,0 @@ "typescript": "~3.1.3" |
442
README.md
@@ -14,7 +14,15 @@ # env-var | ||
Verification, sanitization, and type coercion for environment variables in | ||
Node.js. Supports TypeScript! | ||
<br> | ||
<br> | ||
</div> | ||
Verification, sanitization, and type coercion for environment variables in | ||
Node.js. Particularly useful in TypeScript environments. | ||
* 🏋 Lightweight, at just 4.2kB when minified | ||
* 🧹 Cleaner code, as [shown here](https://gist.github.com/evanshortiss/0cb049bf676b6138d13384671dad750d) | ||
* 🚫 [Fail fast](https://en.wikipedia.org/wiki/Fail-fast) if your environment is misconfigured | ||
* 👩💻 Friendly error messages and example values improve developer experience | ||
* 🎉 TypeScript support provides compile time safety and better developer experience | ||
## Install | ||
@@ -46,10 +54,10 @@ **Note:** env-var requires Node version 8 or later. | ||
.required() | ||
// Convert DB_PASSWORD from base64 to a regular utf8 string (optional) | ||
// Decode DB_PASSWORD from base64 to a utf8 string (optional) | ||
.convertFromBase64() | ||
// Call asString (or other methods) to get the variable value (required) | ||
// Call asString (or other APIs) to get the variable value (required) | ||
.asString(); | ||
// Read in a port (checks that PORT is in the raneg 0 to 65535) or use a | ||
// default value of 5432 instead | ||
const PORT = env.get('PORT', 5432).asPortNumber() | ||
// Read in a port (checks that PORT is in the range 0 to 65535) | ||
// Alternatively, use amdefault value of 5432 if PORT is not defined | ||
const PORT = env.get('PORT').default('5432').asPortNumber() | ||
``` | ||
@@ -62,13 +70,50 @@ | ||
// Read a PORT environment variable and ensure it's a positive number | ||
// An EnvVarError will be thrown if the variable is not set, or is not a number | ||
// Read a PORT environment variable and ensure it's a positive integer. | ||
// An EnvVarError will be thrown if the variable is not set, or if it | ||
// is not a positive integer. | ||
const PORT: number = env.get('PORT').required().asIntPositive(); | ||
``` | ||
## Benefits | ||
Fail fast if your environment is misconfigured. Also, | ||
[this code](https://gist.github.com/evanshortiss/75d936665a2a240fa1966770a85fb137) without | ||
`env-var` would require multiple `assert` calls, other logic, and be more | ||
complex to understand as [demonstrated here](https://gist.github.com/evanshortiss/0cb049bf676b6138d13384671dad750d). | ||
## Usage with dotenv | ||
There is no tight coupling between [env-var](https://www.npmjs.com/package/env-var) | ||
[dotenv](https://www.npmjs.com/package/dotenv). Just `npm install dotenv` and | ||
use it whatever way you're used to. This loose coupling is a good thing since | ||
it reduces package bloat - only install what you need! | ||
You can use `dotenv` with `env-var` via a `require()` calls in your code or | ||
preloading it with the `--require` or `-r` flag in the `node` CLI. | ||
Both examples below assume you have a `.env` file in your repository and it | ||
contains a line similar to `MY_VAR=a-string-value!`. | ||
### Load dotenv via require() | ||
This is per the default usage described by [dotenv's README](https://www.npmjs.com/package/dotenv#usage). | ||
```js | ||
// Read in the .env file | ||
require('dotenv').config() | ||
// Read the MY_VAR entry that dotenv created | ||
const env = require('env-var') | ||
const myVar = env.get('MY_VAR').asString() | ||
``` | ||
### Preload dotenv via CLI Args | ||
This is per the [preload section](https://www.npmjs.com/package/dotenv#preload) | ||
of the dotenv README. Run the following code by using the | ||
`node -r dotenv/config your_script.js` command. | ||
```js | ||
// This is just a regular node script, but we started it using the command | ||
// "node -r dotenv/config your_script.js" via the terminal. This tells node | ||
// to load our variables using dotenv before running the rest of our script! | ||
// Read the MY_VAR entry that dotenv created | ||
const env = require('env-var') | ||
const myVar = env.get('MY_VAR').asString() | ||
``` | ||
## API | ||
@@ -79,8 +124,9 @@ | ||
* module (env-var) | ||
* [EnvVarError()](#envvarerror) | ||
* [from()](#fromvalues-extraaccessors) | ||
* [get()](#getvarname-default) | ||
* [get()](#getvarname) | ||
* [variable](#variable) | ||
* [required()](#requiredisrequired--true) | ||
* [covertFromBase64()](#convertfrombase64) | ||
* [example(string)](#examplestring) | ||
* [default(string)](#defaultstring) | ||
* [asArray()](#asarraydelimiter-string) | ||
@@ -103,30 +149,8 @@ * [asBoolStrict()](#asboolstrict) | ||
* [asUrlString()](#asurlstring) | ||
* [EnvVarError()](#envvarerror) | ||
### EnvVarError() | ||
This is the error class used to represent errors raised by this module. Sample | ||
usage: | ||
```js | ||
const env = require('env-var') | ||
let value = null | ||
try { | ||
// will throw if you have not set this variable | ||
value = env.get('MISSING_VARIABLE').required().asString() | ||
// if catch error is set, we'll end up throwing here instead | ||
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) | ||
} | ||
} | ||
``` | ||
### from(values, extraAccessors) | ||
This function is useful if you're not in a typical Node.js environment, or for | ||
testing. It allows you to generate an env-var instance that reads from the | ||
given `values` instead of the default `process.env`. | ||
given `values` instead of the default `process.env` Object. | ||
@@ -139,149 +163,80 @@ ```js | ||
// apiUrl will be 'https://my.api.com/' | ||
const apiUrl = mockedEnv.get('API_BASE_URL').asUrlString() | ||
const apiUrl = env.get('API_BASE_URL').asUrlString() | ||
``` | ||
#### extraAccessors | ||
When calling `from()` you can also pass an optional parameter containing | ||
additional accessors that will be attached to any variables gotten by that | ||
env-var instance. | ||
When calling `env.from()` you can also pass an optional parameter containing | ||
custom accessors that will be attached to any variables returned by that | ||
env-var instance. This feature is explained in the | ||
[extraAccessors section](#extraAccessors) of these docs. | ||
Accessor functions must accept at least one argument: | ||
### get(varname) | ||
This function has two behaviours: | ||
- `{*} value`: The value that the accessor should process. | ||
1. Calling with a string argument will make it read that value from the environment | ||
2. If no string argument is passed it will return the entire environment object | ||
**Important:** Do not assume that `value` is a string! | ||
Examples: | ||
Example: | ||
```js | ||
const { from } = require('env-var') | ||
const env = require('env-var') | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
// #1 - Read the requested variable and parse it to a positive integer | ||
const limit = env.get('MAX_CONNECTIONS').asIntPositive() | ||
// Add an accessor named 'checkEmail' that verifies that the value is a | ||
// valid-looking email address. | ||
const env = from(process.env, { | ||
checkEmail: (value) => { | ||
const split = String(value).split('@') | ||
// #2 - Returns the entire process.env object | ||
const allVars = env.get() | ||
``` | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
### variable | ||
A variable is returned by calling `env.get(varname)`. It exposes the following | ||
functions to validate and access the underlying value, set a default, or set | ||
an example value: | ||
return value | ||
} | ||
}) | ||
#### example(string) | ||
Allows a developer to provide an example of a valid value for the environment | ||
variable. If the variable is not set (and `required()` was called), or the | ||
variable is set incorrectly this will be included in error output to help | ||
developers diagnose the error. | ||
// We specified 'checkEmail' as the name for the accessor above, so now | ||
// we can call `checkEmail()` like any other accessor. | ||
let validEmail = env.get('ADMIN').checkEmail() | ||
``` | ||
For example: | ||
The accessor function may accept additional arguments if desired; these must be | ||
provided explicitly when the accessor is invoked. | ||
For example, we can modify the `checkEmail()` accessor from above so that it | ||
optionally verifies the domain of the email address: | ||
```js | ||
const { from } = require('env-var') | ||
const env = require('env-var') | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
const ADMIN_EMAIL = env.get('ADMIN_EMAIL') | ||
.required() | ||
.example('admin@example.com') | ||
.asString() | ||
``` | ||
// Add an accessor named 'checkEmail' that verifies that the value is a | ||
// valid-looking email address. | ||
// | ||
// Note that the accessor function also accepts an optional second | ||
// parameter `requiredDomain` which can be provided when the accessor is | ||
// invoked (see below). | ||
const env = from(process.env, { | ||
checkEmail: (value, requiredDomain) => { | ||
const split = String(value).split('@') | ||
If *ADMIN_EMAIL* was not set this code would throw an error similar to that | ||
below to help a developer diagnose the issue: | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
if (requiredDomain && (split[1] !== requiredDomain)) { | ||
throw new Error(`must end with @${requiredDomain}`) | ||
} | ||
return value | ||
} | ||
}) | ||
// We specified 'checkEmail' as the name for the accessor above, so now | ||
// we can call `checkEmail()` like any other accessor. | ||
// | ||
// `env-var` will provide the first argument for the accessor function | ||
// (`value`), but we declared a second argument `requiredDomain`, which | ||
// we can provide when we invoke the accessor. | ||
// Calling the accessor without additional parameters accepts an email | ||
// address with any domain. | ||
let validEmail = env.get('ADMIN').checkEmail() | ||
// If we specify a parameter, then the email address must end with the | ||
// domain we specified. | ||
let invalidEmail = env.get('ADMIN').checkEmail('github.com') | ||
``` | ||
env-var: "ADMIN_EMAIL" is a required variable, but it was not set. An example | ||
of a valid value would be "admin@example.com" | ||
``` | ||
This feature is also available for TypeScript users. The `ExtensionFn` type is | ||
expoed to help in the creation of these new accessors. | ||
#### default(string) | ||
Allows a default value to be provided for use if the desired environment | ||
variable is not set in the program environment. | ||
```ts | ||
import { from, ExtensionFn, EnvVarError } from 'env-var' | ||
Example: | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
const checkEmail: ExtensionFn<string> = (value) => { | ||
const split = String(value).split('@') | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
return value | ||
} | ||
const env = from(process.env, { | ||
checkEmail | ||
}) | ||
// Returns the email string if it's valid, otherwise it will throw | ||
env.get('ADMIN').checkEmail() | ||
``` | ||
### get([varname, [default]]) | ||
You can call this function 3 different ways: | ||
```js | ||
const env = require('env-var') | ||
// #1 - Return the requested variable (we're also checking it's a positive int) | ||
const limit = env.get('SOME_LIMIT').asIntPositive() | ||
// #2 - Return the requested variable, or use the given default if it isn't set | ||
const limit = env.get('SOME_LIMIT', '10').asIntPositive() | ||
// #3 - Return the environment object (process.env by default - see env.from() docs for more) | ||
const allvars = env.get() | ||
// Use POOL_SIZE if set, else use a value of 10 | ||
const POOL_SIZE = env.get('POOL_SIZE').default('10').asIntPositive() | ||
``` | ||
### 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 or empty | ||
this function will throw an `EnvVarError`. If the variable is set it returns itself | ||
so you can access the underlying variable. | ||
Ensure the variable is set on *process.env*. If the variable is not set, or is | ||
set to an empty value, this function will cause an `EnvVarError` to be thrown | ||
when you attempt to read the value using `asString` or a similar function. | ||
Can be bypassed by passing `false`, i.e `required(false)` | ||
The `required()` check can be bypassed by passing `false`, i.e | ||
`required(false)` | ||
Full example: | ||
Example: | ||
@@ -291,17 +246,17 @@ ```js | ||
// Read PORT variable and ensure it's a positive integer. If it is not a | ||
// positive integer, not set or empty the process will exit with an error | ||
// (unless you catch it using a try/catch or "uncaughtException" handler) | ||
// Get the value of NODE_ENV as a string. Could be undefined since we're | ||
// not calling required() before asString() | ||
const NODE_ENV = env.get('NODE_ENV').asString() | ||
const PORT = env.get('PORT').required().asIntPositive() | ||
// If mode is production then this is required, else use default | ||
const SECRET = env.get('SECRET', 'bad-secret').required(NODE_ENV === 'production').asString() | ||
// Read PORT variable and ensure it's in a valid port range. If it's not in | ||
// valid port ranges, not set, or empty an EnvVarError will be thrown | ||
const PORT = env.get('PORT').required().asPortNumber() | ||
app.listen(PORT) | ||
// If mode is production then this is required | ||
const SECRET = env.get('SECRET').required(NODE_ENV === 'production').asString() | ||
``` | ||
#### convertFromBase64() | ||
Sometimes environment variables need to be encoded as base64. You can use this | ||
function to convert them to UTF-8 strings before parsing them. | ||
It's a common need to set an environment variable in base64 format. This | ||
function can be used to decode a base64 environment variable to UTF8. | ||
@@ -319,3 +274,3 @@ For example if we run the script script below, using the command `DB_PASSWORD= | ||
#### asPortNumber() | ||
Converts the value of the environment variable to a string and verifies it's | ||
Converts the value of the environment variable to an integer and verifies it's | ||
within the valid port range of 0-65535. As a result well known ports are | ||
@@ -397,2 +352,25 @@ considered valid by this function. | ||
### EnvVarError() | ||
This is the error class used to represent errors raised by this module. Sample | ||
usage: | ||
```js | ||
const env = require('env-var') | ||
let value = null | ||
try { | ||
// will throw if you have not set this variable | ||
value = env.get('MISSING_VARIABLE').required().asString() | ||
// if catch error is set, we'll end up throwing here instead | ||
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) | ||
} | ||
} | ||
``` | ||
## Examples | ||
@@ -421,3 +399,3 @@ | ||
// Return a float, or 23.2 if not set | ||
const floatVar = env.get('FLOAT', '23.2').asFloat(); | ||
const floatVar = env.get('FLOAT').default('23.2').asFloat(); | ||
@@ -440,2 +418,118 @@ // Return a Boolean. Throws an exception if not set or parsing fails | ||
## extraAccessors | ||
When calling `from()` you can also pass an optional parameter containing | ||
additional accessors that will be attached to any variables gotten by that | ||
env-var instance. | ||
Accessor functions must accept at least one argument: | ||
- `{*} value`: The value that the accessor should process. | ||
**Important:** Do not assume that `value` is a string! | ||
Example: | ||
```js | ||
const { from } = require('env-var') | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
// Add an accessor named 'asEmail' that verifies that the value is a | ||
// valid-looking email address. | ||
const env = from(process.env, { | ||
asEmail: (value) => { | ||
const split = String(value).split('@') | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
return value | ||
} | ||
}) | ||
// We specified 'asEmail' as the name for the accessor above, so now | ||
// we can call `asEmail()` like any other accessor. | ||
let validEmail = env.get('ADMIN').asEmail() | ||
``` | ||
The accessor function may accept additional arguments if desired; these must be | ||
provided explicitly when the accessor is invoked. | ||
For example, we can modify the `asEmail()` accessor from above so that it | ||
optionally verifies the domain of the email address: | ||
```js | ||
const { from } = require('env-var') | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
// Add an accessor named 'asEmail' that verifies that the value is a | ||
// valid-looking email address. | ||
// | ||
// Note that the accessor function also accepts an optional second | ||
// parameter `requiredDomain` which can be provided when the accessor is | ||
// invoked (see below). | ||
const env = from(process.env, { | ||
asEmail: (value, requiredDomain) => { | ||
const split = String(value).split('@') | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
if (requiredDomain && (split[1] !== requiredDomain)) { | ||
throw new Error(`must end with @${requiredDomain}`) | ||
} | ||
return value | ||
} | ||
}) | ||
// We specified 'asEmail' as the name for the accessor above, so now | ||
// we can call `asEmail()` like any other accessor. | ||
// | ||
// `env-var` will provide the first argument for the accessor function | ||
// (`value`), but we declared a second argument `requiredDomain`, which | ||
// we can provide when we invoke the accessor. | ||
// Calling the accessor without additional parameters accepts an email | ||
// address with any domain. | ||
let validEmail = env.get('ADMIN').asEmail() | ||
// If we specify a parameter, then the email address must end with the | ||
// domain we specified. | ||
let invalidEmail = env.get('ADMIN').asEmail('github.com') | ||
``` | ||
This feature is also available for TypeScript users. The `ExtensionFn` type is | ||
exposed to help in the creation of these new accessors. | ||
```ts | ||
import { from, ExtensionFn, EnvVarError } from 'env-var' | ||
// Environment variable that we will use for this example: | ||
process.env.ADMIN = 'admin@example.com' | ||
const asEmail: ExtensionFn<string> = (value) => { | ||
const split = String(value).split('@') | ||
// Validating email addresses is hard. | ||
if (split.length !== 2) { | ||
throw new Error('must contain exactly one "@"') | ||
} | ||
return value | ||
} | ||
const env = from(process.env, { | ||
asEmail | ||
}) | ||
// Returns the email string if it's valid, otherwise it will throw | ||
env.get('ADMIN').asEmail() | ||
``` | ||
## Contributing | ||
@@ -445,5 +539,5 @@ Contributions are welcomed. If you'd like to discuss an idea open an issue, or a | ||
If you want to add a new global accessor, 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: | ||
If you want to add a new global accessor 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: | ||
@@ -453,2 +547,3 @@ ```js | ||
* Validate that the environment value is an integer and equals zero. | ||
* This is a strange example, but hopefully demonstrates the idea. | ||
* @param {String} environmentValue this is the string from process.env | ||
@@ -495,1 +590,4 @@ */ | ||
* @rmblstrp | ||
* @shawnmclean | ||
* @todofixthis | ||
* @xuo |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45841
573
580