nconf-lite/lib/common.mjs

178 lines
4.6 KiB
JavaScript

import fs from 'fs'
import Memory from './stores/memory.mjs'
//
// ### function validkeyvalue(key)
// #### @key {any} key to check
// Return string of key if valid string type key,
// otherwise transform into new key containing
// the error message
export function validkeyvalue(key) {
let type = typeof(key)
if (key && type !== 'string' && type !== 'number') {
return '__invalid_valuetype_of_' + type + '__'
}
return null
}
//
// ### function path (key)
// #### @key {string} The ':' delimited key to split
// Returns a fully-qualified path to a nested nconf key.
// If given null or undefined it should return an empty path.
// '' should still be respected as a path.
//
export function path(key, separator) {
let invalidType = validkeyvalue(key)
if (invalidType) {
return [invalidType]
}
separator = separator || ':'
return key == null
|| key === ''
? []
: key.toString().split(separator)
}
//
// ### function key (arguments)
// Returns a `:` joined string from the `arguments`.
//
export function key(...path) {
return path.map(function(item) {
return validkeyvalue(item) || ('' + item)
}).join(':')
}
//
// ### function key (arguments)
// Returns a joined string from the `arguments`,
// first argument is the join delimiter.
//
export function keyed(separator, ...path) {
return path.map(function(item) {
return validkeyvalue(item) || ('' + item)
}).join(separator)
}
// taken from isobject npm library
export function isObject(val) {
return val != null && typeof val === 'object' && Array.isArray(val) === false
}
// Return a new recursive deep instance of array of objects
// or values to make sure no original object ever get touched
export function mergeRecursiveArray(arr) {
return arr.map(function(item) {
if (isObject(item)) return mergeRecursive({}, item)
if (Array.isArray(item)) return mergeRecursiveArray(item)
return item
})
}
// Recursively merges the child into the parent.
export function mergeRecursive(parent, child) {
Object.keys(child).forEach(key => {
// Arrays will always overwrite for now
if (Array.isArray(child[key])) {
parent[key] = mergeRecursiveArray(child[key])
} else if (child[key] && typeof child[key] === 'object') {
// We don't wanna support cross merging between array and objects
// so we overwrite the old value (at least for now).
if (parent[key] && Array.isArray(parent[key])) {
parent[key] = mergeRecursive({}, child[key])
} else {
parent[key] = mergeRecursive(parent[key] || {}, child[key])
}
} else {
parent[key] = child[key]
}
})
return parent
}
//
// ### function merge (objs)
// #### @objs {Array} Array of object literals to merge
// Merges the specified `objs` together into a new object.
// This differs from the old logic as it does not affect or chagne
// any of the objects being merged.
//
export function merge(orgOut, orgObjs) {
let out = orgOut
let objs = orgObjs
if (objs === undefined) {
out = {}
objs = orgOut
}
if (!Array.isArray(objs)) {
throw new Error('merge called with non-array of objects')
}
for (let x = 0; x < objs.length; x++) {
out = mergeRecursive(out, objs[x])
}
return out
}
//
// ### function capitalize (str)
// #### @str {string} String to capitalize
// Capitalizes the specified `str` if string, otherwise
// returns the original object
//
export function capitalize(str) {
if (typeof(str) !== 'string' && typeof(str) !== 'number') {
return str
}
let out = str.toString()
return out && (out[0].toString()).toUpperCase() + out.slice(1)
}
//
// ### function parseValues (any)
// #### @any {string} String to parse as json or return as is
// try to parse `any` as a json stringified
//
export function parseValues(value) {
if (value === 'undefined') {
return undefined
}
try {
return JSON.parse(value)
} catch (ignore) {
return value
}
}
//
// ### function transform(map, fn)
// #### @map {object} Object of key/value pairs to apply `fn` to
// #### @fn {function} Transformation function that will be applied to every key/value pair
// transform a set of key/value pairs and return the transformed result
export function transform(map, fn) {
var pairs = Object.keys(map).map(function(key) {
var result = fn(key, map[key])
if (!result) {
return null
} else if (result.key) {
return result
}
throw new Error('Transform function passed to store returned an invalid format: ' + JSON.stringify(result))
})
return pairs
.filter(function(pair) {
return pair !== null
})
.reduce(function(accumulator, pair) {
accumulator[pair.key] = pair.value
return accumulator
}, {})
}