You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/* @flow */ /*::
type DotenvParseOptions = { debug?: boolean }
// keys and values from src
type DotenvParseOutput = { [string]: string }
type DotenvConfigOptions = { path?: string, // path to .env file
encoding?: string, // encoding of .env file
debug?: string // turn on logging for debugging purposes
}
type DotenvConfigOutput = { parsed?: DotenvParseOutput, error?: Error }
*/
const fs = require('fs') const path = require('path') const os = require('os')
function log (message /*: string */) { console.log(`[dotenv][DEBUG] ${message}`) }
const NEWLINE = '\n' const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/ const RE_NEWLINES = /\\n/g const NEWLINES_MATCH = /\r\n|\n|\r/
// Parses src into an Object
function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ { const debug = Boolean(options && options.debug) const obj = {}
// convert Buffers before splitting into lines and processing
src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) { // matching "KEY' and 'VAL' in 'KEY=VAL'
const keyValueArr = line.match(RE_INI_KEY_VAL) // matched?
if (keyValueArr != null) { const key = keyValueArr[1] // default undefined or missing values to empty string
let val = (keyValueArr[2] || '') const end = val.length - 1 const isDoubleQuoted = val[0] === '"' && val[end] === '"' const isSingleQuoted = val[0] === "'" && val[end] === "'"
// if single or double quoted, remove quotes
if (isSingleQuoted || isDoubleQuoted) { val = val.substring(1, end)
// if double quoted, expand newlines
if (isDoubleQuoted) { val = val.replace(RE_NEWLINES, NEWLINE) } } else { // remove surrounding whitespace
val = val.trim() }
obj[key] = val } else if (debug) { log(`did not match key and value when parsing line ${idx + 1}: ${line}`) } })
return obj }
function resolveHome (envPath) { return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath }
// Populates process.env from .env file
function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ { let dotenvPath = path.resolve(process.cwd(), '.env') let encoding /*: string */ = 'utf8' let debug = false
if (options) { if (options.path != null) { dotenvPath = resolveHome(options.path) } if (options.encoding != null) { encoding = options.encoding } if (options.debug != null) { debug = true } }
try { // specifying an encoding returns a string instead of a buffer
const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })
Object.keys(parsed).forEach(function (key) { if (!Object.prototype.hasOwnProperty.call(process.env, key)) { process.env[key] = parsed[key] } else if (debug) { log(`"${key}" is already defined in \`process.env\` and will not be overwritten`) } })
return { parsed } } catch (e) { return { error: e } } }
module.exports.config = config module.exports.parse = parse
|