Search code examples
node.jsiniconfigparser

nodejs read .ini config file


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.


Solution

  • 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.