Last active
November 18, 2020 12:00
-
-
Save joepuzzo/e777519f079c954277995e706299f590 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -------------------- toPath -------------------- */ | |
const toPath = (path = '') => { | |
return String.prototype.replace | |
.call(path, /\['(.+?)'\]/g, '.$1') | |
.split(/[,[\].]+?/) | |
.filter(Boolean); | |
} | |
/* --------------------- get --------------------- */ | |
const get = (obj, path = '', defaultValue) => { | |
const result = String.prototype.replace | |
.call(path, /\['(.+?)'\]/g, '.$1') | |
.split(/[,[\].]+?/) | |
.filter(Boolean) | |
.reduce( | |
(res, key) => (res !== null && res !== undefined ? res[key] : res), | |
obj | |
); | |
return result === undefined || result === obj ? defaultValue : result; | |
}; | |
/* --------------------- has --------------------- */ | |
// NOTE: two helper functions for has | |
// foo --> | |
// foo.bar --> foo | |
// foo.bar[3] --> foo.bar | |
// foo.bar.baz[2].raz.taz[5].laz --> foo.bar.baz[2].raz.taz[5] | |
const parentPath = (path) => { | |
return `.${path}`.replace(/(.*)[.[].*/, '$1').replace(/\./, ''); | |
} | |
// foo --> foo | |
// foo.bar --> bar | |
// foo.bar[3] --> [3] | |
// foo.bar.baz[2].raz.taz[5].laz --> laz | |
const pathKey = (path) => { | |
return path.replace(parentPath(path), '').replace(/\./, ''); | |
} | |
const has = (obj, path) => { | |
const pPath = parentPath(path); | |
const key = pathKey(path); | |
// If we have parent path then get the object at that location | |
// .. otherwise its the root object | |
const parentObj = pPath ? get(obj, pPath) : obj; | |
// If its [3] turn key into 3 | |
return !!(parentObj && Object.hasOwnProperty.call(parentObj, key.replace(/\[(.*)\]/, '$1'))); | |
} | |
/* --------------------- set --------------------- */ | |
const set = (obj, path = '', val) => { | |
const result = String.prototype.replace | |
.call(path, /\['(.+?)'\]/g, '.$1') | |
.split(/[,[\].]+?/) | |
.filter(Boolean) | |
.reduce( | |
(res, key, i, arr) => { | |
//console.log('RES', res, 'Key', key, 'I', i, 'Arr', arr, 'OBJ', obj); | |
// At the leaf set the value | |
if( i === arr.length - 1){ | |
res[key] = val; | |
return res[key]; | |
} | |
// Initialize to new array or object if needed | |
if( res[key] === undefined ){ | |
if(Number.isInteger(+(arr[i+1]))) { | |
res[key] = []; | |
} else { | |
res[key] = {}; | |
} | |
return res[key]; | |
} | |
// Exception for if the value is changeing to an array | |
if (Number.isInteger(+arr[i + 1]) && !Array.isArray(res[key])) { | |
res[key] = []; | |
} | |
// Otherwise keep whats there | |
return res[key]; | |
}, | |
obj | |
); | |
}; | |
/* --------------------- unset --------------------- */ | |
const unset = (obj, path = '') => { | |
let found = false; | |
String.prototype.replace | |
.call(path, /\['(.+?)'\]/g, '.$1') | |
.split(/[,[\].]+?/) | |
.filter(Boolean) | |
.reduce( | |
(res, key, i, arr) => { | |
// Base case res is undefined | |
if(res === undefined){ | |
return res; | |
} | |
// At the leaf delete the value | |
if( i === arr.length - 1){ | |
delete res[key]; | |
found = true; | |
return res[key]; | |
} | |
// Otherwise keep going | |
return res[key]; | |
}, | |
obj | |
); | |
return found; | |
}; | |
/* --------------------- values --------------------- */ | |
const values = (obj = {}) => { | |
const props = Object.keys(obj); | |
return props.map((key) => obj[key]) | |
} | |
/* --------------------- pullAt --------------------- */ | |
const pullAt = (obj, path = '') => { | |
let pulled; | |
String.prototype.replace | |
.call(path, /\['(.+?)'\]/g, '.$1') | |
.split(/[,[\].]+?/) | |
.filter(Boolean) | |
.reduce( | |
(res, key, i, arr) => { | |
// Base case res is undefined | |
if(res === undefined){ | |
return res; | |
} | |
// At the leaf delete the value | |
if( i === arr.length - 1 && Array.isArray(res)){ | |
// Pull out one value at index ( key ) | |
pulled = res.splice(key, 1); | |
return res[key]; | |
} | |
// Otherwise keep going | |
return res[key]; | |
}, | |
obj | |
); | |
return pulled; | |
}; | |
/* --------------------- test logs --------------------- */ | |
const testObj = { | |
foo: { | |
bar: [ | |
{ baz: 'hello' } | |
] | |
} | |
}; | |
console.log('--------- TEST TOPATH --------'); | |
console.log('undefined ---->', toPath()); | |
console.log('foo ---->', toPath('foo')); | |
console.log('foo.bar[0] ---->', toPath('foo.bar[0]')); | |
console.log('foo.bar[0].baz ---->', toPath('foo.bar[0].baz')); | |
console.log('foo.bar[3].baz ---->', toPath('foo.bar[3].baz')); | |
console.log('foo.bar.baz[0].taz.bar[10][3].bar.0.5 ---->', toPath('foo.bar.baz[0].taz.bar[10][3].bar.0.5')); | |
console.log("foo['bar'].baz[0].taz.bar[10][3].bar['0'].5 ----> ", toPath("foo['bar'].baz[0].taz.bar[10][3].bar['0'].5")); | |
console.log('\n'); | |
console.log('-------- TEST VALUES --------'); | |
console.log(JSON.stringify(testObj), '---->', values(testObj)); | |
console.log(JSON.stringify({}), '---->', values({})); | |
console.log(JSON.stringify({ foo: 1, bar: 'baz' }), '---->', values({ foo: 1, bar: 'baz' })); | |
console.log(JSON.stringify(), '---->', values()); | |
console.log('\n'); | |
console.log('---------- TEST HAS ----------'); | |
console.log(JSON.stringify(testObj)); | |
console.log('foo ---->', has(testObj, 'foo')); | |
console.log('foo.bar[0] ---->', has(testObj, 'foo.bar[0]')); | |
console.log('foo.bar[0].baz ---->', has(testObj, 'foo.bar[0].baz')); | |
console.log('foo.bar[3].baz ---->', has(testObj, 'foo.bar[3].baz')); | |
console.log('\n'); | |
console.log('---------- TEST GET ----------');; | |
console.log(JSON.stringify(testObj)); | |
console.log('undefined ---->', get(testObj)); | |
console.log('foo ---->', get(testObj, 'foo')); | |
console.log('foo.bar[0] ---->', get(testObj, 'foo.bar[0]')); | |
console.log('foo.bar[0].baz ---->', get(testObj, 'foo.bar[0].baz')); | |
console.log('foo.bar[3].baz ---->', get(testObj, 'foo.bar[3].baz')); | |
console.log('\n'); | |
console.log('---------- TEST SET ----------'); | |
let testSetObj = {}; | |
console.log(JSON.stringify(testSetObj)); | |
console.log('foo ----> {}', set(testSetObj, 'foo', {})); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('foo.bar[0] ----> { baz: "hello" }', set(testSetObj, 'foo.bar[0]', { baz: 'hello' })); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('\n'); | |
testSetObj = {}; | |
console.log('foo.bar[0].baz ----> "hello"', set(testSetObj, 'foo.bar[0].baz', 'hello')); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('foo.bar[3].baz ----> "world"', set(testSetObj, 'foo.bar[3].baz', 'world')); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('foo.bar[3].baz ----> "change"', set(testSetObj, 'foo.bar[3].baz', 'change')); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('foo.laz ----> "world"', set(testSetObj, 'foo.laz', 'world')); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('\n'); | |
testSetObj = {}; | |
console.log('foo ----> "hello"', set(testSetObj, 'foo', 'hello')); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('\n'); | |
testSetObj = {}; | |
console.log('foo.bar.baz[0].taz.bar[10][3].bar.0.5 ----> 3', set(testSetObj, 'foo.bar.baz[0].taz.bar[10][3].bar.0.5', 3)); | |
console.log(JSON.stringify(testSetObj)); | |
console.log('\n'); | |
console.log('---------- TEST UNSET ----------'); | |
let testUnsetObj = {}; | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo ---->', unset(testUnsetObj, 'foo')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo.bar[0] ---->', unset(testUnsetObj, 'foo.bar[0]')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('\n'); | |
testUnsetObj = { foo: { bar: [{ baz: 'hello' }, { raz: 'world'}] } }; | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo.bar[0] ---->', unset(testUnsetObj, 'foo.bar[0]')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo.bar[1].raz ---->', unset(testUnsetObj, 'foo.bar[1].raz')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo ---->', unset(testUnsetObj, 'foo')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('---------- TEST PULLAT ----------'); | |
testUnsetObj = {}; | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo ---->', pullAt(testUnsetObj, 'foo')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('\n'); | |
console.log('foo.bar[0] ---->', pullAt(testUnsetObj, 'foo.bar[0]')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('\n'); | |
testUnsetObj = { foo: { bar: [{ baz: 'hello' }, { raz: 'world'}] } }; | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo.bar[0] ---->', pullAt(testUnsetObj, 'foo.bar[0]')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('\n'); | |
console.log('foo.bar[1].raz ---->', pullAt(testUnsetObj, 'foo.bar[1].raz')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('foo ---->', pullAt(testUnsetObj, 'foo')); | |
console.log(JSON.stringify(testUnsetObj)); | |
console.log('\n'); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment