@ou-imdt/utils
Version:
Utility library for interactive media development
46 lines (42 loc) • 1.61 kB
JavaScript
import splitPropertyPath from './splitPropertyPath.js';
/**
* Sets the value at the specified path of an object.
* Supports propertyPathRegex groups @see {@link propertyPathRegex}.
* @param {object} target - The object in which to set the value.
* @param {string} path - The dot/bracket notation path specifying where to set the value.
* @param {*} value - The value to set at the specified path.
* @returns {boolean} `true` if successful, otherwise `false`.
*/
export default function setObjectProperty(target, path, value) {
const parts = splitPropertyPath(path, true);
const convert = {
'?': val => Boolean(val),
'$': val => String(val),
'#': val => Number(val),
default: val => val
};
for (const el of parts) {
const { part, before, key, type, after } = el;
try {
path = path.slice(part.length);
if (typeof target[key] === 'undefined') {
const nextPart = parts[parts.indexOf(el) + 1];
const expectsArray = (type === '[]') || (!Number.isNaN(parseInt(nextPart?.key)) && /[^'"]/.test(`${nextPart?.before}${nextPart?.after}`));
target[key] = (expectsArray ? [] : {});
}
if (type === '[]') {
return value.every((el, index) => setObjectProperty(target[key], `[${index}]${path}`, el));
}
if (parts.indexOf(el) < parts.length - 1) {
target = target[key];
continue;
}
target[key] = convert[type ?? 'default'](value);
return true;
} catch(err) {
console.error(`unable to set object property '${key}':`, err);
return false;
}
}
return false;
}