UNPKG

@strattadb/environment

Version:

Environment variable configuration for Node.js made easy.

112 lines (92 loc) 2.62 kB
import EnvironmentVariableError from './EnvironmentVariableError'; import { Parser } from './parsers'; import { logDebug } from './debug'; export type Env<TSchemaData> = { [TKey in keyof TSchemaData]: TSchemaData[TKey]; }; /** * A schema defines the environment variable * requirements. */ export type Schema<TSchemaData> = { [TKey in keyof TSchemaData]: SchemaEntry<TSchemaData[TKey]>; }; export type SchemaEntry<TType> = { /** * The parser function used to parse * the environment variable string. */ parser: Parser<TType>; /** * The name of the environment variable variable to look up. */ envVarName: string; /** * Helper text describing the variable. */ description?: string; } & SchemaEntryRequiredInfo<TType>; export type SchemaEntryRequiredInfo<TType> = | { required: true; defaultValue?: undefined; } | { required: false; /** * The default value to be used if the env variable is not defined. * It will not be parsed or validated. */ defaultValue: TType; }; /** * Returns an env object based on a schema. */ export function makeEnv<TSchemaData extends Record<string, any>>( schema: Schema<TSchemaData>, processEnv: NodeJS.ProcessEnv = process.env, ): Env<TSchemaData> { logDebug('making env object...'); const env = Object.entries(schema).reduce((acc, [key, schemaEntry]) => { const value = getValue(key, schemaEntry, processEnv); return { ...acc, [key]: value }; }, {}) as Env<TSchemaData>; logDebug('env object ready: %o', env); return env; } function getValue<TType>( key: string, schemaEntry: SchemaEntry<TType>, processEnv: NodeJS.ProcessEnv, ): TType { const envVarValue = processEnv[schemaEntry.envVarName]; if (envVarValue === undefined) { if (schemaEntry.required) { let message = `${schemaEntry.envVarName} is required but is not set`; if (schemaEntry.description) { message += `. Variable description: ${schemaEntry.description}`; } throw new EnvironmentVariableError(message); } return schemaEntry.defaultValue; } const value = parseEnvVarValue(key, envVarValue, schemaEntry); return value; } function parseEnvVarValue<TType>( key: string, serializedValue: string, schemaEntry: SchemaEntry<TType>, ): TType { let value: TType; try { value = schemaEntry.parser(serializedValue); } catch (error) { throw new EnvironmentVariableError( `${key} has invalid format. Reason: ${ (error as Error).message }. Got: '${serializedValue}'`, ); } return value; }