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.
		
		
		
		
			
				
					114 lines
				
				2.9 KiB
			
		
		
			
		
	
	
					114 lines
				
				2.9 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								/* @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')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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 = /\n|\r|\r\n/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// 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
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// 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 = 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
							 |