2

I have a config file. It has variables stored in the following manner.

[general]
webapp=/var/www
data=/home/data


[env]
WEBAPP_DEPLOY=${general:webapp}/storage/deploy
SYSTEM_DEPLOY=${general:data}/deploy

As you can see it has 2 sections general and env. Section env uses the variables from section general.

So I want to read this file into a variable. Let's say config. Here's I want config object to look like:

{
    general: {
        webapp: '/var/www',
        data: '/home/data'
    },
    env: {
        WEBAPP_DEPLOY: '/var/www/storage/deploy',
        SYSTEM_DEPLOY: '/home/data/deploy'
    }
}

I general I am looking for a config parser for nodejs that supports string interpolation.

Amarjit Singh
  • 2,068
  • 19
  • 52

1 Answers1

1

I would assume most ini libraries don't include the variable expansion functionality, but with lodash primitives a generic "deep object replacer" isn't too complex.

I've switched the : delimiter for . so has and get can lookup values directly.

const { get, has, isPlainObject, reduce } = require('lodash')

// Match all tokens like `${a.b}` and capture the variable path inside the parens
const re_token = /\${([\w$][\w\.$]*?)}/g

// If a string includes a token and the token exists in the object, replace it
function tokenReplace(value, key, object){
  if (!value || !value.replace) return value
  return value.replace(re_token, (match_string, token_path) => {
    if (has(object, token_path)) return get(object, token_path)
    return match_string
  })
}

// Deep clone any plain objects and strings, replacing tokens
function plainObjectReplacer(node, object = node){
  return reduce(node, (result, value, key) => {
    result[key] = (isPlainObject(value))
      ? plainObjectReplacer(value, object)
      : tokenReplace(value, key, object)
    return result
  }, {})
}
> plainObjectReplacer({ a: { b: { c: 1 }}, d: 'wat', e: '${d}${a.b.c}' })
{ a: { b: { c: 1 } }, d: 'wat', e: 'wat1' }

You'll find most config management tools (like ansible) can do this sort of variable expansion for you before app runtime, at deployment.

Matt
  • 68,711
  • 7
  • 155
  • 158