简体   繁体   English

如何将环境变量转换为 JS 中的对象?

[英]How do I convert an environment variable to an object in JS?

I'm trying to convert an environment variable into an object of values for configuration in JavaScript but I don't know the best way to achieve this.我正在尝试将环境变量转换为 JavaScript 中的配置值对象,但我不知道实现这一目标的最佳方法。

The idea would be to output SAMPLE_ENV_VAR=value as:这个想法是将SAMPLE_ENV_VAR=value输出为:

{
    sample: {
        env: {
            var: value
        }
    }
}

What I have so far:到目前为止我所拥有的:

const _ = require('lodash');
const process = require('process');

_.each(process.env, (value, key) => {
    key = key.toLowerCase().split('_');
    // Convert to object here
}

Here's a more complete solution based on yours:这是基于您的更完整的解决方案:

const _ = require('lodash');
const result = {};

// We'll take the following as an example:
// process.env = { HELLO_WORLD_HI: 5 }
// We'll expect the following output:
// result = { hello: { world: { hi: 5 } } }
_.each(process.env, (value, key) => {
    // We'll separate each key every underscore.
    // In simple terms, this will turn:
    // "HELLLO_WORLD_HI" -> ['HELLO', 'WORLD', 'HI']
    const keys = key.toLowerCase().split('_');

    // We'll start on the top-level object
    let current = result;

    // We'll assign here the current "key" we're iterating on
    // It will have the values:
    // 'hello' (1st loop), 'world' (2nd), and 'hi' (last)
    let currentKey;

    // We'll iterate on every key. Moreover, we'll
    // remove every key (starting from the first one: 'HELLO')
    // and assign the removed key as our "currentKey".
    // currentKey = 'hello', keys = ['world', 'hi']
    // currentKey = 'world', keys = ['hi'], and so on..
    while ( (currentKey = keys.shift()) ) {
        // If we still have any keys to nest,
        if ( keys.length ) {
          // We'll assign that object property with an object value
          // result =// { HELLO: {} }
          current[currentKey] = {};

          // And then move inside that object so
          // could nest for the next loop
          // 1st loop: { HELLO: { /*We're here*/ } }
          // 2nd loop: { HELLO: { WORLD: { /*We're here*/ } } }
          // 3rd loop: { HELLO: { WORLD: { HI : { /*We're here*/ } } } }
          current = current[currentKey];
        } else {
          // Lastly, when we no longer have any key to nest
          // e.g., we're past the third loop in our example
          current[currentKey] = process.env[key]
        }
    }
});

console.log(result);

To simply put:简单地说:

  • We'll loop through every environment variable ( from process.env )我们将遍历每个环境变量( from process.env
  • Split the key name with an underscore, and, again, loop each key ( ['HELLO', 'WORLD', 'HI'] )用下划线分割键名,并再次循环每个键( ['HELLO', 'WORLD', 'HI']
  • Assign it to an object ( { hello: {} } -> { hello: { world: {} } } -> { hello: world: { hi: ? } } } )将它分配给一个对象( { hello: {} } -> { hello: { world: {} } } -> { hello: world: { hi: ? } } }
  • When we no longer have any keys left, assign it to the actual value ( { hello: { world: { hi: 5 } } } )当我们不再有任何键时,将其分配给实际值( { hello: { world: { hi: 5 } } }

Funnily enough, I just finished code for this last night for a personal project.有趣的是,我昨晚刚刚完成了一个个人项目的代码。 What I ended up using is not ideal, but is working for me:我最终使用的并不理想,但对我有用:

export function keyReducer(
  src: any,
  out: any,
  key: string,
  pre: string,
  del: string
): ConfigScope {
  const path = key.toLowerCase().split(del);
  if (path[0] === pre.toLowerCase()) {
    path.shift();
  }

  if (path.length === 1) { // single element path
    const [head] = path;
    out[head] = src[key];
  } else {
    const tail = path.pop();
    const target = path.reduce((parent: any, next: string) => {
      if (parent[next]) {
        return parent[next];
      } else {
        return (parent[next] = <ConfigScope>{});
      }
    }, out);
    target[tail] = src[key];
  }
  return out;
}

static fromEnv(env: Environment, {prefix = 'ABC', delimiter = '_'} = {}) {
  const data: ConfigScope = Object.keys(env).filter(key => {
    return StringUtils.startsWith(key, prefix);
  }).reduce((out, key) => {
    return keyReducer(env, out, key, prefix, '_');
  }, <ConfigScope>{});
  return new Config(data);
}

(with TypeScript type annotations) (带有 TypeScript 类型注释)

The idea here is to split each key, create the target objects on the way down, then set the final value.这里的想法是拆分每个键,在向下的过程中创建目标对象,然后设置最终值。

This is my quick take at it:这是我的快速理解:

var object = {}; // the object to store the value in 
var name = "SAMPLE_ENV_VAR"; // the environment variable key
var value = "value"; // the value of the environment variable

// helper function to automatically create an inner object if none exists
function getOrCreateInnerObj(obj, name) {
  if (!obj.hasOwnProperty()) {
    obj[name] = {};
  }
  return obj[name];
}

// an array of the individual parts (e.g. ["sample", "env", "var"])
var keyParts = name.toLowerCase().split("_");

// innerObj will contain the second to last element object in the tree based on the array of keys
var innerObj = getOrCreateInnerObj(object, keyParts[0]);
for (var i = 1; i < keyParts.length - 1; i++) {
  innerObj = getOrCreateInnerObj(innerObj, keyParts[i]);
}

// set the value itself
innerObj[keyParts[keyParts.length - 1]] = value;

$("body").html(JSON.stringify(object));

The gist of it is, for all but the last element in the array of key parts, you get or create an object in the current parent object for that key, and once you've repeated this for all but the last key, you'll have the second-to-last inner object, which you can then set the value on.它的要点是,对于除关键部分数组中的最后一个元素之外的所有元素,您都可以在当前父对象中为该键获取或创建一个对象,一旦您对除最后一个键之外的所有键重复此操作,您就可以“将有倒数第二个内部对象,然后您可以设置该值。

Edit: Working example编辑:工作示例

Edit 2: Here is a much cleaner example that uses a little bit of recursion to accomplish the same thing编辑 2:是一个更清晰的例子,它使用一点递归来完成同样的事情

const basic = {};
let current;
`YOUR_VARIABLE_NAME`
  .split(`_`)
  .forEach((item, index, array) => {
    if(index === 0) {
      return current = basic[item] = {};
    }
    if(index === array.length - 1) {
      return current[item] = process.env.HE_LO_NA;
    }
    current = current[item] = {};
});

console.log(require('util').inspect(basic, {depth: 10}));
const _ = require('lodash');
const process = require('process');

const result = Object.entries(process.env).reduce((acc, [key, value]) => {
    _.set(acc, key.toLowerCase().replace('_', '.'), value);
    return acc;
}, {})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM