File

libs/nx/src/generators/journey-src/lib/env-parsing/env.ts

Description

A a key-value object to be easily processed by other functions.

{a: 1, b:"value"}

Index

Properties

Indexable

[key: string]:

Properties

BFF_BASE_URL (Optional)
Type string
HEADER_LOGO_LINK_URL (Optional)
Type string
PERSIST_ACL_POLICY_URL (Optional)
Type string
import { Tree } from '@nx/devkit';

/**
 * A a key-value object to be easily processed
 * by other functions.
 *
 * {a: 1, b:"value"}
 */
export interface EnvOptionObject {
  BFF_BASE_URL?: string;
  PERSIST_ACL_POLICY_URL?: string;
  HEADER_LOGO_LINK_URL?: string;
  [key: string]: unknown;
}

export interface ReadEnvOptions {
  envFilePath?: string;
  envValues?: string[];
}

/**
 * Combines a given config of environment details with a separate list of env values
 * given through the CLI. CLI values will override static config values.
 * CLI values need to have the following format.
 *
 * The constructed env object returned by this function will then look like this:
 * ```
 * {
 *   KEY_A: 'value'
 *   KEY_B: 'some other value if `KEY_B` is present in process.env'
 * }
 * ```
 */
export function readEnv(tree: Tree, options: ReadEnvOptions): EnvOptionObject {
  const envFromFile = readEnvFromFile(tree, options.envFilePath);
  const envFromCli = parseEnvOptions(options.envValues ?? []);

  // resulting env object with defaults
  const env = {
    BFF_BASE_URL: '',
    PERSIST_ACL_POLICY_URL: '',
    TRACKING_APP_NAME: '',
    TRACKING_ADOBE_URL: '',
    HEADER_LOGO_LINK_URL: '',
    ...envFromFile,
    ...envFromCli
  };

  return env;
}

/**
 * Read and parse env options from a plain text file
 * in the format:
 * A=1
 * B=value
 */
function readEnvFromFile(tree: Tree, envPath?: string): EnvOptionObject {
  if (envPath) {
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const envFileContent = tree.read(envPath)!.toString();
    return parseEnvFile(envFileContent);
  }

  return {};
}

/**
 * Cherry picked from dotenv
 * via https://github.com/motdotla/dotenv/blob/7301ac9be0b2c766f865bbe24280bf82586d25aa/lib/main.js
 */
function parseEnvFile(content: string): EnvOptionObject {
  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/;
  const obj: Record<string, string> = {};

  content.split(NEWLINES_MATCH).forEach(function (line) {
    // matching "KEY' and 'VAL' in 'KEY=VAL'
    const keyValueArr = line.match(RE_INI_KEY_VAL);

    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;
    }
  });

  return obj;
}

/**
 * Parse options given through the CLI.
 * Pass in a key only to retrieve the value from the process environment (via process.env)
 * or pass in a `key=value` combination similar to the file format to provide an explicit value.
 *
 * The result is a key-value object
 * {a: 1, b:"value"}
 *
 */
function parseEnvOptions(overrides: string[]): EnvOptionObject {
  const overrideMap = overrides.reduce((accu: Record<string, string | undefined>, item) => {
    const parts = item.split('=');
    const [key, value] = parts;

    if (key && value) {
      accu[key] = value;
    } else if (parts.length === 1 && key && process.env[key]) {
      const envValue = process.env[key];
      accu[key] = envValue;
    } else {
      accu[key] = '';
    }

    return accu;
  }, {});

  return overrideMap;
}

results matching ""

    No results matching ""