@formulier/core
Version:
Simple, performant form library
84 lines (83 loc) • 2.65 kB
JavaScript
import clone from 'shallow-clone';
import isEqual from 'lodash.isequal';
function getPath(source, path, fallback) {
let p = 0;
const pathArray = toPath(path);
while (source && p < pathArray.length) {
source = source[pathArray[p++]];
if (typeof source === 'string' && p < pathArray.length - 1)
return fallback;
}
return source === undefined ? fallback : source;
}
function setPath(obj, path, value) {
const res = clone(obj);
let resVal = res;
let i = 0;
const pathArray = toPath(path);
for (; i < pathArray.length - 1; i++) {
const currentPath = pathArray[i];
const currentObj = getPath(obj, pathArray.slice(0, i + 1));
if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {
resVal = resVal[currentPath] = clone(currentObj);
}
else {
const nextPath = pathArray[i + 1];
resVal = resVal[currentPath] = isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};
}
}
if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {
return obj;
}
if (value === undefined) {
delete resVal[pathArray[i]];
}
else {
resVal[pathArray[i]] = value;
}
if (i === 0 && value === undefined) {
delete res[pathArray[i]];
}
return res;
}
function setKey(source, key, value) {
if (isEqual(source[key], value)) {
return source;
}
return { ...source, [key]: value };
}
function removeKey(source, key) {
if (!Object.prototype.hasOwnProperty.call(source, key)) {
return source;
}
return Object.fromEntries(Object.entries(source).filter(entry => entry[0] !== key));
}
function toPath(path) {
if (Array.isArray(path))
return path;
const result = [];
const rePropName = /[^.[\]]+|\[(?:([^"'][^[]*)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
const reEscapeChar = /\\(\\)?/g;
if (path.charCodeAt(0) === '.'.charCodeAt(0)) {
result.push('');
}
path.replace(rePropName, (match, expression, quote, subString) => {
let key = match;
if (quote) {
key = subString.replace(reEscapeChar, '$1');
}
else if (expression) {
key = expression.trim();
}
result.push(key);
return '';
});
return result;
}
function isInteger(source) {
return String(Math.floor(Number(source))) === source;
}
function isObject(source) {
return source !== null && typeof source === 'object';
}
export { clone, isEqual, getPath, setPath, setKey, removeKey, toPath, isInteger, isObject };