nhb-toolbox
Version:
A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.
166 lines (165 loc) • 5.64 kB
JavaScript
import { isDateLike } from '../date/guards.js';
import { isFileOrBlob } from '../form/guards.js';
import { isEmptyObject, isNotEmptyObject, isObject } from '../guards/non-primitives.js';
import { isDeepEqual } from '../utils/index.js';
import { parseObjectValues } from './sanitize.js';
export const mergeObjects = (...objects) => {
const map = new Map();
for (const obj of objects) {
for (const key in obj) {
const existingValue = map.get(key);
if (isNotEmptyObject(obj[key])) {
if (isNotEmptyObject(existingValue)) {
if (isDateLike(obj[key]) || isFileOrBlob(obj[key])) {
map.set(key, obj[key]);
}
else {
map.set(key, mergeObjects(existingValue, obj[key]));
}
}
else {
map.set(key, obj[key]);
}
}
else {
map.set(key, obj[key]);
}
}
}
const result = {};
map?.forEach((value, key) => {
result[key] = value;
});
return result;
};
export const mergeAndFlattenObjects = (...objects) => {
const map = new Map();
const _flattenObject = (obj, parentKey = '') => {
for (const key in obj) {
const newKey = parentKey ? `${String(parentKey)}.${key}` : key;
if (isNotEmptyObject(obj[key])) {
if (isDateLike(obj[key]) || isFileOrBlob(obj[key])) {
map.set(newKey, obj[key]);
}
else {
_flattenObject(obj[key], newKey);
}
}
else {
map.set(newKey, obj[key]);
}
}
};
for (const obj of objects) {
_flattenObject(obj);
}
const result = {};
map?.forEach((value, key) => {
result[key] = value;
});
return result;
};
export const flattenObjectKeyValue = (object) => {
const flattened = {};
for (const [key, value] of Object.entries(object)) {
if (isNotEmptyObject(value)) {
const nestedFlattened = flattenObjectKeyValue(value);
if (isDateLike(value) || isFileOrBlob(value)) {
flattened[key] = value;
}
else {
Object.assign(flattened, nestedFlattened);
}
}
else {
flattened[key] = value;
}
}
return flattened;
};
export const flattenObjectDotNotation = (object) => {
const _flattenObject = (source, prefix = '') => {
const flattened = {};
for (const [key, value] of Object.entries(source)) {
const newKey = prefix ? `${String(prefix)}.${key}` : key;
if (isNotEmptyObject(value) || isFileOrBlob(value)) {
if (isDateLike(value)) {
flattened[newKey] = value;
}
else {
Object.assign(flattened, _flattenObject(value, newKey));
}
}
else {
flattened[newKey] = value;
}
}
return flattened;
};
return _flattenObject(object);
};
export const extractUpdatedFields = (baseObject, updatedObject) => {
const updatedFields = {};
for (const key in updatedObject) {
if (key in baseObject && !isDeepEqual(updatedObject[key], baseObject[key])) {
if (updatedObject[key] && isNotEmptyObject(updatedObject[key])) {
updatedFields[key] = extractUpdatedFields(baseObject[key], updatedObject[key]);
if (updatedFields[key] && isEmptyObject(updatedFields[key])) {
delete updatedFields[key];
}
}
else {
updatedFields[key] = updatedObject[key];
}
}
}
return updatedFields;
};
export const extractNewFields = (baseObject, updatedObject) => {
const newFields = {};
for (const key in updatedObject) {
if (!(key in baseObject)) {
newFields[key] = updatedObject[key];
}
else if (isNotEmptyObject(updatedObject[key]) && isNotEmptyObject(baseObject[key])) {
const nestedNewFields = extractNewFields(baseObject[key], updatedObject[key]);
if (isNotEmptyObject(nestedNewFields)) {
newFields[key] = nestedNewFields;
}
}
}
return newFields;
};
export const extractUpdatedAndNewFields = (baseObject, updatedObject) => {
const updatedFields = {};
const newFields = {};
for (const key in updatedObject) {
if (!(key in baseObject)) {
newFields[key] = updatedObject[key];
}
else if (!isDeepEqual(updatedObject[key], baseObject[key])) {
if (updatedObject[key] && isNotEmptyObject(updatedObject[key])) {
updatedFields[key] = extractUpdatedAndNewFields(baseObject[key], updatedObject[key]);
if (updatedFields[key] && isEmptyObject(updatedFields[key])) {
delete updatedFields[key];
}
}
else {
updatedFields[key] = updatedObject[key];
}
}
}
return { ...updatedFields, ...newFields };
};
export const parseJsonToObject = (value, parsePrimitives = true) => {
try {
const data = JSON.parse(value);
if (!isObject(data)) {
return {};
}
return parsePrimitives ? parseObjectValues(data) : data;
}
catch {
return {};
}
};