@wxn0brp/db
Version:
A simple file-based database management system with support for CRUD operations, custom queries, and graph structures.
146 lines (145 loc) • 4.54 kB
JavaScript
/**
* Updates an object with new values.
* @param obj - The object to update.
* @param fields - An object containing new values to update in the target object.
*/
export default function updateObjectAdvanced(obj, fields) {
if (typeof fields !== "object" || fields === null) {
throw new Error("Fields must be an object or object array");
}
const fieldsArray = Array.isArray(fields) ? fields : [fields];
for (const field of fieldsArray) {
if (typeof field !== "object" || field === null) {
throw new Error("Fields must be an object or object array");
}
updateAdvanced(obj, field);
const fieldsSubset = removeAdvancedOperators({ ...field });
updateObject(obj, fieldsSubset);
}
return obj;
}
function updateAdvanced(obj, fields) {
updateArray(obj, fields);
updateNested(obj, fields);
updateIncrement(obj, fields);
updateUnset(obj, fields);
updateRename(obj, fields);
}
function removeAdvancedOperators(fields) {
const advancedOperators = [
"push", "pushset", "pull", "pullall",
"inc", "dec",
"unset",
"merge",
"rename"
].map(operator => "$" + operator);
advancedOperators.forEach(operator => delete fields[operator]);
return fields;
}
function updateArray(obj, fields) {
if ("$push" in fields) {
for (const [key, value] of Object.entries(fields["$push"])) {
if (Array.isArray(obj[key])) {
obj[key].push(value);
}
else {
obj[key] = [value];
}
}
}
if ("$pushset" in fields) {
for (const [key, value] of Object.entries(fields["$pushset"])) {
if (Array.isArray(obj[key])) {
obj[key].push(value);
}
else {
obj[key] = [value];
}
obj[key] = [...new Set(obj[key])];
}
}
if ("$pull" in fields) {
for (const [key, value] of Object.entries(fields["$pull"])) {
if (Array.isArray(obj[key])) {
obj[key] = obj[key].filter(item => item !== value);
}
}
}
if ("$pullall" in fields) {
for (const [key, values] of Object.entries(fields["$pullall"])) {
if (Array.isArray(obj[key])) {
obj[key] = obj[key].filter(item => !values.includes(item));
}
}
}
}
function updateNested(obj, fields) {
if ("$merge" in fields) {
for (const [key, value] of Object.entries(fields["$merge"])) {
if (typeof obj[key] === "object" && typeof value === "object") {
obj[key] = { ...obj[key], ...value };
}
else {
obj[key] = value;
}
}
}
}
function updateIncrement(obj, fields) {
if ("$inc" in fields) {
for (const [key, value] of Object.entries(fields["$inc"])) {
if (typeof obj[key] === "number" && typeof value === "number") {
obj[key] += value;
}
else if (!(key in obj)) {
obj[key] = value;
}
else {
throw new Error(`Cannot increment non-numeric value at key: ${key}`);
}
}
}
if ("$dec" in fields) {
for (const [key, value] of Object.entries(fields["$dec"])) {
if (typeof obj[key] === "number" && typeof value === "number") {
obj[key] -= value;
}
else if (!(key in obj)) {
obj[key] = value;
}
else {
throw new Error(`Cannot decrement non-numeric value at key: ${key}`);
}
}
}
}
function updateUnset(obj, fields) {
if ("$unset" in fields) {
for (const key of Object.keys(fields["$unset"])) {
delete obj[key];
}
}
}
function updateRename(obj, fields) {
if ("$rename" in fields) {
for (const [oldKey, newKey] of Object.entries(fields["$rename"])) {
if (oldKey in obj) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
}
}
}
/**
* Updates an object with new values.
* @param obj - The object to update.
* @param newVal - An object containing new values to update in the target object.
*/
function updateObject(obj, newVal) {
for (let key in newVal) {
if (newVal.hasOwnProperty(key)) {
obj[key] = newVal[key];
}
}
return obj;
}