super-utils-plus
Version:
A superior alternative to Lodash with improved performance, TypeScript support, and developer experience
86 lines (85 loc) • 2.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.result = result;
const is_1 = require("../utils/is");
/**
* Resolves the value at path of object. If the resolved value is a function
* it's invoked with the `this` binding of its parent object.
*
* @param object - The object to query
* @param path - The path of the property to resolve
* @param defaultValue - The value returned for undefined resolved values
* @returns The resolved value
*/
function result(object, path, defaultValue) {
if ((0, is_1.isNil)(object)) {
return resolveDefaultValue(defaultValue, undefined);
}
const segments = normalizePath(path);
if (!segments.length) {
return object;
}
let current = object;
let parent = object;
for (const segment of segments) {
if ((0, is_1.isNil)(current)) {
return resolveDefaultValue(defaultValue, parent);
}
parent = current;
current = current[segment];
}
if (current === undefined) {
return resolveDefaultValue(defaultValue, parent);
}
return (0, is_1.isFunction)(current) ? current.call(parent) : current;
}
function normalizePath(path) {
if ((0, is_1.isString)(path)) {
return parsePath(path);
}
if ((0, is_1.isArray)(path)) {
return path;
}
return [path];
}
function resolveDefaultValue(value, thisArg) {
return (0, is_1.isFunction)(value) ? value.call(thisArg) : value;
}
function parsePath(path) {
const segments = [];
let currentSegment = '';
let inBrackets = false;
for (let index = 0; index < path.length; index++) {
const character = path[index];
if (character === '[') {
if (currentSegment) {
segments.push(currentSegment);
currentSegment = '';
}
inBrackets = true;
}
else if (character === ']') {
if (/^\d+$/.test(currentSegment)) {
segments.push(parseInt(currentSegment, 10));
}
else {
segments.push(currentSegment);
}
currentSegment = '';
inBrackets = false;
}
else if (character === '.' && !inBrackets) {
if (currentSegment) {
segments.push(currentSegment);
currentSegment = '';
}
}
else {
currentSegment += character;
}
}
if (currentSegment) {
segments.push(currentSegment);
}
return segments;
}