Spaces:
Sleeping
Sleeping
| ; | |
| const Assert = require('./assert'); | |
| const internals = {}; | |
| module.exports = function (obj, chain, options) { | |
| if (chain === false || | |
| chain === null || | |
| chain === undefined) { | |
| return obj; | |
| } | |
| options = options || {}; | |
| if (typeof options === 'string') { | |
| options = { separator: options }; | |
| } | |
| const isChainArray = Array.isArray(chain); | |
| Assert(!isChainArray || !options.separator, 'Separator option no valid for array-based chain'); | |
| const path = isChainArray ? chain : chain.split(options.separator || '.'); | |
| let ref = obj; | |
| for (let i = 0; i < path.length; ++i) { | |
| let key = path[i]; | |
| const type = options.iterables && internals.iterables(ref); | |
| if (Array.isArray(ref) || | |
| type === 'set') { | |
| const number = Number(key); | |
| if (Number.isInteger(number)) { | |
| key = number < 0 ? ref.length + number : number; | |
| } | |
| } | |
| if (!ref || | |
| typeof ref === 'function' && options.functions === false || // Defaults to true | |
| !type && ref[key] === undefined) { | |
| Assert(!options.strict || i + 1 === path.length, 'Missing segment', key, 'in reach path ', chain); | |
| Assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain); | |
| ref = options.default; | |
| break; | |
| } | |
| if (!type) { | |
| ref = ref[key]; | |
| } | |
| else if (type === 'set') { | |
| ref = [...ref][key]; | |
| } | |
| else { // type === 'map' | |
| ref = ref.get(key); | |
| } | |
| } | |
| return ref; | |
| }; | |
| internals.iterables = function (ref) { | |
| if (ref instanceof Set) { | |
| return 'set'; | |
| } | |
| if (ref instanceof Map) { | |
| return 'map'; | |
| } | |
| }; | |