EnvVars
Type : class
The EnvVars
class is a versatile utility designed for type-safe access to environment variables. It simplifies handling environment variables by offering features such as type parsing, retrieving values tailored to specific environments, reading from various sources, and marking variables as dynamic. Additionally, it ensures robust error handling, preventing your application from proceeding with unexpected behavior when issues arise.
Imagine the following scenario:
let PORT = +(process.env.PORT || 3000);let HOST = process.env.HOST || 'localhost';if (process.env.NODE_ENV === 'production') { PORT = +process.env.PRODUCTION_PORT || throw new Error('Missing production port'); HOST = process.env.PRODUCTION_HOST || throw new Error('Missing production host');}
This code snippet can become cumbersome to write, maintain, and debug, especially when you have multiple environments and the same variable is used in different places throughout your app.
The EnvVars
class makes this code much easier to read and maintain, while also providing additional features and robust error handling.
Let’s take a look at how it works:
-
Imagine your process.env object looks like this:
{PORT: 3000,PRODUCTION_PORT: 5000,} -
Create an
envVars.ts
file:export const envVars = new EnvVars({mapObj: {port: {parseAs: 'number',whenNodeEnvIs: {production: 'PRODUCTION_PORT',anyEnv: 'PORT',}},}}); -
EnvVars
takes care of everything by selecting the appropriate value for the current environment, converting it to the correct type, marking it as dynamic if specified, and handling any errors.
Then you can use the previousenvVars.ts
file in your code as follows:import { envVars } from './envVars';console.log(envVars.port); // process.env.NODE_ENV === 'production' ? 5000 : 3000 -
if the currentEnv is
production
the previous example will log the number5000
else it will log the number3000
Full Example
SECRET_VALUES=1,2,3,4
import { EnvVars } from '@mustib/utils/node';
export const fromObject = { PORT: '3000',}
export const envVars = new EnvVars({ useDynamicValues: true, enumerable: true, sources: { fromFile: 'path to .env file', fromObject, fromDynamicFunction: () => ({ HOST: 'localhost', }) }, mapObj: { port: { parseAs: 'number', whenNodeEnvIs: { anyEnv: 'PORT', }}, host: { whenNodeEnvIs: { anyEnv: 'HOST', }}, secretValues: { parseAs(data) { return data.varValueForCurrentEnv.split(',') }, whenNodeEnvIs: { anyEnv: 'SECRET_VALUES', } } }})
import { envVars, fromObject } from './envVars';
console.log(envVars) // { port: 3000, host: 'localhost', secretValues: [ '1', '2', '3', '4' ] }
fromObject.PORT = '5000'console.log(envVars) // { port: 5000, host: 'localhost', secretValues: [ '1', '2', '3', '4' ] }
console.log(Object.keys(envVars)) // [ 'port', 'host', 'secretValues' ]
Constructor()
type EnvVars = new (options: ConstructorParams<EnvVarsMapObj>): EnvVars
parameters
an object with the following properties:-
useDynamicValues:
- A
boolean
indicates whether the generated env object should be dynamic or not. - Defaults to
false
.
- A
-
sources
: Used to define the source of environment variables, which can be one of the following:- A
string
representing the path to a.env
file - A single EnvVarsSourcesObj object, or an array of such objects.
- A
-
mapObj:
EnvVarsMapObj -
currentEnv:
- a
string
representing the current env. - defaults to
process.env.NODE_ENV
.
- a
-
enumerable:
- a
boolean
indicates whether the generated env object should be enumerable or not. - defaults to
false
.
- a
-
EnvVarsMapObj
type EnvVarsMapObj = { [varName: string]: { parseAs?: ParseAsString | ParseAsFunction whenNodeEnvIs: { [envName: string | 'anyEnv']: string } useDynamicValue?: boolean }}
An object with variable names as keys and their configuration as object with the following properties:
-
parseAs:
used to convert the value of the env-var from string to the specified type, possible values are:- A
string
with the value of"string"
,"number"
,"bool"
,"date"
where each value corresponds to a predefinedparseAsFunction
. - A user-defined function whose return value determines the value and type of the environment variable.
- see parseAsFunction for more details.
- A
-
whenNodeEnvIs:
an object defining the environment variables that should be used for each environment.- see whenNodeEnvIs for more details.
-
useDynamicValue:
aboolean
indicates if the value is dynamic and will be parsed again every time it is needed
EnvVarsSourcesObj
type EnvVarsSourcesObj = { fromFile: string; fromObject: Record<string, string>; fromDynamicFunction(): Record<string, string>;};
An object that represents a source of environment variables with the following properties:
fromFile:
Astring
representing the path to a.env
file.fromObject:
An object with environment variables.fromDynamicFunction:
A function that returns an object with environment variables.
parseAsFunction
type ParseAsFunction = (data: { combinedEnvVars: Record<string, string>[]; varValueForCurrentEnv: string; currentEnv: string; assignedSource: Record<string, string>; varNameForCurrentEnv: string;}) => any
A user-defined function whose return value determines the value and type of the environment variable.
It will be called with a data
object with the following properties:
-
combinedEnvVars:
an array of objects, each representing a source defined in theEnvVars
constructor’s sources. -
varValueForCurrentEnv:
the value of the varNameForCurrentEnv in assignedSource object. -
currentEnv:
the current environment (the keys of thewhenNodeEnvIs
object). -
assignedSource:
the first object from combinedEnvVars that has the varNameForCurrentEnv -
varNameForCurrentEnv:
the name of the environment variable for the current environment (the value of the currentEnv from thewhenNodeEnvIs
object).
For example:
ifwhenNodeEnvIs
has this value:const whenNodeEnvIs = {production: 'Prod_VAR',anyEnv: 'ANY_VAR',};then the
varNameForCurrentEnv
will beProd_VAR
forproduction
andANY_VAR
foranyEnv
whenNodeEnvIs
type WhenNodeEnvIs = Record<string | 'anyEnv', string>
An object where the keys are possible environment names and the values are any valid key from combined sources object passed to the EnvVars
constructor.
For example, if the environment is production
, the value of the key production
will be used. If the environment is development
, the value of the key development
will be used, and so on. If sources has PORT
and HOST
as variables, then possible values for the whenNodeEnvIs
object are PORT
and HOST
.
The special key anyEnv
can be used to specify a fallback value for any environment. This is useful when you want to provide a default value for an environment variable that is not defined in the current environment.