diff options
author | Minteck <contact@minteck.org> | 2022-06-04 08:51:01 +0200 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2022-06-04 08:51:01 +0200 |
commit | 383285ecd5292bf9a825e05904955b937de84cc9 (patch) | |
tree | 0a53b6f02c1604b078044567c03dc1b6c944c8c2 /node_modules/dot-prop/index.js | |
download | equestriadb-383285ecd5292bf9a825e05904955b937de84cc9.tar.gz equestriadb-383285ecd5292bf9a825e05904955b937de84cc9.tar.bz2 equestriadb-383285ecd5292bf9a825e05904955b937de84cc9.zip |
Initial commit
Diffstat (limited to 'node_modules/dot-prop/index.js')
-rw-r--r-- | node_modules/dot-prop/index.js | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/node_modules/dot-prop/index.js b/node_modules/dot-prop/index.js new file mode 100644 index 0000000..a90f599 --- /dev/null +++ b/node_modules/dot-prop/index.js @@ -0,0 +1,142 @@ +'use strict'; +const isObj = require('is-obj'); + +const disallowedKeys = [ + '__proto__', + 'prototype', + 'constructor' +]; + +const isValidPath = pathSegments => !pathSegments.some(segment => disallowedKeys.includes(segment)); + +function getPathSegments(path) { + const pathArray = path.split('.'); + const parts = []; + + for (let i = 0; i < pathArray.length; i++) { + let p = pathArray[i]; + + while (p[p.length - 1] === '\\' && pathArray[i + 1] !== undefined) { + p = p.slice(0, -1) + '.'; + p += pathArray[++i]; + } + + parts.push(p); + } + + if (!isValidPath(parts)) { + return []; + } + + return parts; +} + +module.exports = { + get(object, path, value) { + if (!isObj(object) || typeof path !== 'string') { + return value === undefined ? object : value; + } + + const pathArray = getPathSegments(path); + if (pathArray.length === 0) { + return; + } + + for (let i = 0; i < pathArray.length; i++) { + if (!Object.prototype.propertyIsEnumerable.call(object, pathArray[i])) { + return value; + } + + object = object[pathArray[i]]; + + if (object === undefined || object === null) { + // `object` is either `undefined` or `null` so we want to stop the loop, and + // if this is not the last bit of the path, and + // if it did't return `undefined` + // it would return `null` if `object` is `null` + // but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied value, not `null` + if (i !== pathArray.length - 1) { + return value; + } + + break; + } + } + + return object; + }, + + set(object, path, value) { + if (!isObj(object) || typeof path !== 'string') { + return object; + } + + const root = object; + const pathArray = getPathSegments(path); + + for (let i = 0; i < pathArray.length; i++) { + const p = pathArray[i]; + + if (!isObj(object[p])) { + object[p] = {}; + } + + if (i === pathArray.length - 1) { + object[p] = value; + } + + object = object[p]; + } + + return root; + }, + + delete(object, path) { + if (!isObj(object) || typeof path !== 'string') { + return false; + } + + const pathArray = getPathSegments(path); + + for (let i = 0; i < pathArray.length; i++) { + const p = pathArray[i]; + + if (i === pathArray.length - 1) { + delete object[p]; + return true; + } + + object = object[p]; + + if (!isObj(object)) { + return false; + } + } + }, + + has(object, path) { + if (!isObj(object) || typeof path !== 'string') { + return false; + } + + const pathArray = getPathSegments(path); + if (pathArray.length === 0) { + return false; + } + + // eslint-disable-next-line unicorn/no-for-loop + for (let i = 0; i < pathArray.length; i++) { + if (isObj(object)) { + if (!(pathArray[i] in object)) { + return false; + } + + object = object[pathArray[i]]; + } else { + return false; + } + } + + return true; + } +}; |