Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/modules-modules / dotenv / registerDotEnv.ts
Size: Mime:
/**
 * @private
 * @fileoverview loads .env files for the env
 * @borrows https://github.com/motdotla/dotenv
 */
import { existsSync, readFileSync } from 'fs'
import { resolve } from 'path'
import {
  AbsolutePathString,
  DotEnvValues,
  DotEnvConfigOptions,
} from './typings'

/**
 * @private
 * @description parses a string or buffer into an object
 * @param src - source to be parsed
 * @returns keys and values from src
 */
function parse(src: string | Buffer) {
  const obj = {}

  // convert Buffers before splitting into lines and processing
  src
    .toString()
    .split('\n')
    .forEach(line => {
      // matching "KEY' and 'VAL' in 'KEY=VAL'
      const keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)
      // matched?
      if (keyValueArr !== null) {
        const key = keyValueArr[1]

        // default undefined or missing values to empty string
        let value = keyValueArr[2] || ''

        // expand newlines in quoted values
        const len = value ? value.length : 0
        if (
          len > 0 &&
          value.charAt(0) === '"' &&
          value.charAt(len - 1) === '"'
        ) {
          value = value.replace(/\\n/gm, '\n')
        }

        // remove any surrounding quotes and extra spaces
        value = value.replace(/(^['"]|['"]$)/g, '').trim()

        obj[key] = value
      }
    })

  return obj
}

/**
 * @private
 * @param [options=undefined]
 * @return path to .env file
 */
function getOptions(options: DotEnvConfigOptions): DotEnvConfigOptions {
  let path = '.env'
  let encoding = 'utf8'

  if (options !== undefined) {
    if (options.path) {
      path = options.path
    }
    if (options.encoding) {
      encoding = options.encoding
    }
  }

  return { path, encoding }
}

// const DOT_ENV = []
process.env.DOT_ENV = '\n'

/**
 * @private
 * @description main entry point into dotenv. Allows configuration before loading .env
 *
 * @return {Object} parsed object or error
 */
function config(options: DotEnvConfigOptions) {
  const { path, encoding } = getOptions(options)

  try {
    // specifying an encoding returns a string instead of a buffer
    const content = readFileSync(path, { encoding })
    const parsedObj = parse(content)

    Object.keys(parsedObj).forEach(key => {
      const value = parsedObj[key]
      // if (hasOwnProp(process.env, key)) {
      process.env[key] = value
      process.env.DOT_ENV += `${key}=${value}\n`
      // process.env.DOT_ENV[key] = value
      // process.env.DOT_ENV.push([key, value])
    })

    return { parsed: parsedObj }
  } catch (parseError) {
    return { error: parseError }
  }
}

/**
 * @private
 * @param envFileResolutionOrder
 */
function loadEnv(envFileResolutionOrder: AbsolutePathString[]): void {
  // Find the first env file path match.
  const envFilePath = envFileResolutionOrder.find(existsSync)
  // console.log({ envFilePath })

  // If we found an env file match the register it.
  if (envFilePath) {
    const message = `==> Registering environment variables from: ${envFilePath}`
    // const colored = colors.bgBlue.white(message)
    // console.log(colored)
    console.log(message)
    config({ path: envFilePath })
  }
}

/**
 * @private
 * @see loadEnv
 *
 * @example @name env.data/LiquidAss
 */
function registerEnvFile(
  envFile = '.env',
  DEPLOYMENT = process.env.DEPLOYMENT
): void {
  // This is the order in which we will try to resolve an environment configuration
  // file.
  const envFileResolutionOrder = [
    // Is there an environment config file at the app root?
    // This always takes preference.
    // e.g. /projects/react-universally/.env
    // resolve(appRootDir, envFile),
    // Is there an environment config file at the app root for our target
    // environment name?
    // e.g. /projects/react-universally/.env.staging
  ]

  const APP_ROOT_PATH = process.env.APP_ROOT_PATH

  if (DEPLOYMENT) {
    const DEPLOYMENT_DOT_ENV = resolve(
      APP_ROOT_PATH,
      `${envFile}.${DEPLOYMENT}`
    )
    // console.log(DEPLOYMENT_DOT_ENV)
    // envFileResolutionOrder.push(DEPLOYMENT_DOT_ENV)
    envFileResolutionOrder.unshift(DEPLOYMENT_DOT_ENV)
    envFileResolutionOrder.unshift(`${DEPLOYMENT_DOT_ENV}/.env`)
  }

  // console.log({ envFileResolutionOrder })

  loadEnv(envFileResolutionOrder)
}

/**
 * @todo autofix here?
 * @alias fromQueryStringToObj
 */
function loadFromDotEnvString(
  DOT_ENV: string = process.env.DOT_ENV
): DotEnvValues {
  const obj = {}

  // could .reduce
  DOT_ENV.split('\n')
    .filter(String)
    .map(string => string.split('='))
    .forEach(([key, value]) => (obj[key] = value))

  return obj
}

export { registerEnvFile }
export { loadFromDotEnvString }
export { loadEnv }