added pathToString helper.  Wrote helper tests for pathToString, getKeys, and walkPath
master
Kebler Network System Administrator 2021-05-09 09:45:38 -07:00
parent 958e46afd9
commit 1681f56326
3 changed files with 61 additions and 12 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@uci-utils/obj-nested-prop",
"version": "0.1.0",
"version": "0.1.1",
"description": "Functions to get set, delete, and search nested properties of an object",
"main": "src/obj-nested-prop.js",
"type": "module",
@ -43,4 +43,4 @@
"mocha": "^8.4.0",
"nodemon": "^2.0.7"
}
}
}

View File

@ -1,9 +1,9 @@
import { check } from '@uci-utils/type'
import { logger } from '@uci-utils/logger'
const log = logger({ file: '/src/obj-prop.js', package: '@uci-utils/obj-prop' })
const log = logger({ file: '/src/obj-nested-prop.js', package: '@uci-utils/obj-nested-prop' })
const set = (obj, path, value, opts = {}) => {
function set (obj, path, value, opts = {}) {
if (value === undefined) return del(obj, path)
const keys = validateArgs(obj, path, opts)
if (!keys) return obj
@ -65,7 +65,7 @@ function get (obj, path) {
return value
}
const getKeys = (path, opts = {}) => {
function getKeys (path, opts = {}) {
if (!(check.isString(path) || check.isArray(path) || check.isSymbol(path))) {
log.warn({ function: 'getKeys', path: path, msg: 'path was not valid' })
return false
@ -98,12 +98,13 @@ const getKeys = (path, opts = {}) => {
return keys
}
function validateArgs (obj, path, opts) {
if (!check.isObject(obj)) {
log.warn({ function: 'del', obj: obj, msg: 'passed is not an object' })
return false
function pathToString (path, opts = {}) {
const keys = getKeys(path, opts)
if (keys.reduce((res, key) => res && !check.isSymbol(key), true)) return keys.join(opts.dot || '.')
else {
log.warn({ function: 'pathToString', path: path, keys: keys, opts: opts, msg: 'unable to make string of path' })
return null
}
return getKeys(path, opts)
}
function walkPath (obj, keys) {
@ -117,6 +118,7 @@ function walkPath (obj, keys) {
last = last[keys[i]]
if (!last) {
log.warn({ function: 'walkPath', obj: obj, keys: keys, key: keys[i], msg: 'key is not in object, aborting walk' })
// will return undefined
break
}
log.trace({ function: 'walkPath', curProp: last, msg: 'fetching... deep property' })
@ -124,6 +126,16 @@ function walkPath (obj, keys) {
return last
}
// non exported local functions
const validateArgs = (obj, path, opts) => {
if (!check.isObject(obj)) {
log.warn({ function: 'del', obj: obj, msg: 'passed is not an object' })
return false
}
return getKeys(path, opts)
}
const isNumber = value => {
if (value.trim() !== '') {
const number = Number(value)
@ -144,4 +156,4 @@ const isValidKey = key => {
return true
}
export { set, get, del, getKeys, walkPath }
export { set, get, del, getKeys, walkPath, pathToString }

View File

@ -1,5 +1,5 @@
import assert from 'assert'
import { get, set, del } from '../src/obj-nested-prop.js'
import { get, set, del, getKeys, walkPath, pathToString } from '../src/obj-nested-prop.js'
import { check } from '@uci-utils/type'
const date = new Date(Date.now())
@ -291,3 +291,40 @@ describe('options.split', () => {
assert.strictEqual(o.a['b.c.d'].e, 'c')
})
})
describe('helpers', () => {
it('getKeys: will split path as string or array into array of single keys', () => {
const test = 'atest'
const key = Symbol('akey')
assert.deepStrictEqual(getKeys('this.is\\.a.string'), ['this', 'is.a', 'string'])
assert.deepStrictEqual(getKeys(['this.is.a.string', key, test]),
['this', 'is', 'a', 'string', key, 'atest'])
})
it('pathToString: converts path with getKeys and returns joined string', () => {
const p1 = ['this', 'is%an', 'array']
const p2 = [['this', 'is%an', 'array'], { dot: '#', delimiter: '.%' }]
// console.log(pathToString(p1))
// console.log(pathToString(...p2))
assert.deepStrictEqual(pathToString(p1), 'this.is%an.array')
assert.deepStrictEqual(pathToString(...p2), 'this#is#an#array')
})
it('pathToString: returns null if unable to make string (e.g. path contains Symbol)', () => {
const p1 = [['this', Symbol('test'), 'array'], { dot: '#', delimiter: '.%' }]
// console.log('has symbol', pathToString(...p1))
assert.strictEqual(pathToString(...p1), null)
})
it('walkPath: will walk an array of keys deep into object', () => {
const path = 'this.is.a.value'
const path2 = 'this.is.a.bogus.value'
const path3 = 'this.is.object'
const o = {}
set(o, path, 'some value')
set(o, path3, { a: 'what', b: 'when' })
assert.strictEqual(walkPath(o, getKeys(path)), 'some value')
assert.strictEqual(walkPath(o, getKeys(path2)), undefined)
assert.deepStrictEqual(walkPath(o, getKeys(path3)), { a: 'what', b: 'when' })
})
})