Source: layers/env.js

'use strict';

const AbstractLayer = require('./abstract');

/**
 * Layer that uses process.env as the source of data, with filter by `prefix` and even a JSON parsing!
 * @extends AbstractLayer
 */
class EnvLayer extends AbstractLayer {
  /**
   * @inheritDoc
   */
  async init() {
    this.normalizePrefix();
    this.parseEnv();
    this.markInitialized();
  }

  /**
   * Parse process.env and get data
   * @private
   */
  parseEnv() {
    const { env } = process;
    Object.keys(env).forEach((key) => {
      if (env[key] === undefined) return;
      if (!this.options.prefix) return this.parseField(key, env[key]);

      if (!key.startsWith(this.options.prefix)) return;
      const trimmedKey = key.replace(new RegExp(`^${this.options.prefix}${this.options.parsingSeparator}`), '');
      return this.parseField(trimmedKey, env[key]);
    });
  }

  /**
   * Parse env field
   * @param {string} key
   * @param {*} value
   * @private
   */
  parseField(key, value) {
    const path = key.replace(new RegExp(this.options.parsingSeparator, 'g'), this.constructor.SEPARATOR);
    if (!this.options.json) return this.set(path, value);
    try {
      this.set(path, JSON.parse(value));
    } catch (e) {
      console.error(`JSON value in key ${key} fallback to string. Error:`, e);
      this.set(path, value);
    }
  }

  /**
   * Remove ending `parsingSeparator`, if present in `prefix`
   * @private
   */
  normalizePrefix() {
    const separator = this.options.parsingSeparator;
    if (this.options.prefix === undefined || !this.options.prefix.endsWith(separator)) return;
    this.options.prefix = this.options.prefix.replace(new RegExp(`(.*)${separator}`), '$1');
  }
}

module.exports = EnvLayer;