memconfig
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

memconfig

npm version minzipped size build status codecov types included


Manage project-wide configuration from an immutable in-memory store, using a friendly interface powered by lodash's get/set path-like selectors.

Table of contents

  1. Motivation
  2. Installation
  3. Usage
  4. API
  5. Best practices

Motivation

I find myself writing the same module in different projects, and the libraries I found are overkill for what I need, so I decided to distribute it as a small package.

And it goes pretty well with merge-files-content Node.JS module!

Installation

Before installing, you need to install lodash by yourself, since it's a peerDependency.

In case your project doesn't already uses it, run npm i lodash.

npm i memconfig

or

yarn add memconfig

Usage

This module works both in the browser and Node.JS environments. Let's see some examples:

Database configs in Node

const { Config } = require('memconfig')

const config = new Config()
config.set('database.port', 3001)
config.get('database').port === 3001 // true
config.get(['database', 'host'], 'default-host') // "default-host"

User UI (serializable) settings in the browser

import { Config } from 'memconfig' // es6 supported!

const config = new Config()
// user enables dark mode
config.set('userSettings.darkMode', true)

// Then you have to persist local settings
localStorage.setItem('ui_config', config.toString())
// The config can be deserialized with the from() method
const config = Config.from(localStorage.getItem('ui_config'))
config.get('userSettings') // {"darkMode": true}

API

🔧 Config

The Config objects accepts an object of settings:

new Config({
  /**
   * If true, every object is going to be clonned in order
   * to prevent side-effect mutations
   */
  immutable: true,
})

🔧 config.setStore(store)

Use config.setStore(yourOwnObject) to initialize it with your app defaults.

🔧 config.freeze()

Freeze the Config instance and prevent new values to be inserted into the store. It shall throw an Error if config.set() is called while config.frozen is true.

Use config.unfreeze() to unfreeze.

⚠️ For Node.JS, it is advisable to use this method once your app starts if you're clustering it, to ensure that nobody tries to mutate configurations at runtime.

🔧 config.get(valuePath, defaultValue)

Internally it uses lodash's get to resolve valuePath keys.

🔧 config.set(valuePath, value)

Internally it uses lodash's set.

🔧 config.merge(obj | Config)

Merges the given object (or instance of Config) into the store.

🔧 config.delete(valuePath)

Internally it uses lodash's unset.

🔧 config.toString()

Same as doing JSON.stringify(config.store).

🔧 Config.from(serializedStore, configSettings)

Static method to create an instance of Config out of a "stringified" store.

Accepts a second parameter to pass settings to the constructor.

Best practices

💎 Don't overuse get and set methods; "get once"

As simple as setting object properties should be, these methods are not linear. That means your program will iterate over many objects when you use valuePaths like level1.level2 or ['level1', 'level2', 'level3'] to access some value in the store

So always try to cache the first levels of the objects you need at module level, and use the values as a normal object. For instance:

DO:

const config = require('../config')

const databaseConfig = config.get('database', { port: 3001 })

const getDatabasePort = () => databaseConfig.port

DON'T:

const config = require('../config')

const getDatabasePort = () => config.get('database.port', 3001)

💎 Clustered apps: "forget about set() at runtime"

Since we're talking about in-memory stores, each instance of your clustered Node.JS app will have its own instance of the Config object, hence you shouldn't use set() anymore after the fork() is done, because the forked processes won't see their config objects updated.

If that's a problem for you, an in-memory store may not be what you're looking for but something like a KVS or such things.

So the implementation should be:

const config = require('./config')
const { config: database } = require('./modules/database')
const { config: storage } = require('./modules/storage')
const app = require('./app')

config.setStore({ database, storage })
// Freeze the store to throw an error if somebody tries to set() something at runtime
config.freeze()

app.start() // now create you app's cluster

Package Sidebar

Install

npm i memconfig

Weekly Downloads

5

Version

1.0.0

License

MIT

Unpacked Size

33.1 kB

Total Files

13

Last publish

Collaborators

  • frondor