UNPKG

@wxn0brp/db

Version:

A simple file-based database management system with support for CRUD operations, custom queries, and graph structures.

177 lines (176 loc) 5.79 kB
import hasFields from "./hasFields.js"; /** * Checks if an object meets the criteria specified in the fields with operators. */ export default function hasFieldsAdvanced(obj, fields) { if (typeof fields !== "object" || fields === null) { throw new Error("Fields must be an object"); } if ("$and" in fields) { return fields["$and"].every(subFields => hasFieldsAdvanced(obj, subFields)); } if ("$or" in fields) { return fields["$or"].some(subFields => hasFieldsAdvanced(obj, subFields)); } // Check various conditions if (!checkConditions(obj, fields)) return false; const fieldsSubset = removeAdvancedOperators({ ...fields }); return hasFields(obj, fieldsSubset); } function removeAdvancedOperators(fields) { const advancedOperators = [ "and", "or", "gt", "lt", "gte", "lte", "in", "nin", "exists", "type", "regex", "arrinc", "arrincall", "size", "startsWith", "endsWith", "between", "not", "subset" ].map(operator => "$" + operator); advancedOperators.forEach(operator => delete fields[operator]); return fields; } function checkConditions(obj, fields) { return (checkComparison(obj, fields) && checkExistence(obj, fields) && checkType(obj, fields) && checkRegex(obj, fields) && checkArrayConditions(obj, fields) && checkStringConditions(obj, fields) && checkBetween(obj, fields) && checkNot(obj, fields) && checkSubset(obj, fields)); } function checkComparison(obj, fields) { const comparisonOperators = ["$gt", "$lt", "$gte", "$lte", "$in", "$nin"]; for (const operator of comparisonOperators) { if (operator in fields) { for (const entries of Object.entries(fields[operator])) { const [key, value] = entries; switch (operator) { case "$gt": if (!(obj[key] > value)) return false; break; case "$lt": if (!(obj[key] < value)) return false; break; case "$gte": if (!(obj[key] >= value)) return false; break; case "$lte": if (!(obj[key] <= value)) return false; break; case "$in": if (!value.includes(obj[key])) return false; break; case "$nin": if (value.includes(obj[key])) return false; break; } } } } return true; } function checkExistence(obj, fields) { if ("$exists" in fields) { for (const [key, shouldExist] of Object.entries(fields["$exists"])) { if (shouldExist && !(key in obj)) return false; if (!shouldExist && (key in obj)) return false; } } return true; } function checkType(obj, fields) { if ("$type" in fields) { for (const [key, type] of Object.entries(fields["$type"])) { if (typeof obj[key] !== type) return false; } } return true; } function checkRegex(obj, fields) { if ("$regex" in fields) { for (const [key, regex] of Object.entries(fields["$regex"])) { if (!regex.test(obj[key])) return false; } } return true; } function checkArrayConditions(obj, fields) { if ("$arrinc" in fields) { for (const [key, values] of Object.entries(fields["$arrinc"])) { if (!Array.isArray(obj[key]) || !values.some(val => obj[key].includes(val))) return false; } } if ("$arrincall" in fields) { for (const [key, values] of Object.entries(fields["$arrincall"])) { if (!Array.isArray(obj[key]) || !values.every(val => obj[key].includes(val))) return false; } } if ("$size" in fields) { for (const [key, size] of Object.entries(fields["$size"])) { if (Array.isArray(obj[key]) || typeof obj[key] === "string") { if (obj[key].length !== size) return false; } else { return false; } } } return true; } function checkStringConditions(obj, fields) { if ("$startsWith" in fields) { for (const [key, value] of Object.entries(fields["$startsWith"])) { if (typeof obj[key] !== "string" || !obj[key].startsWith(value)) return false; } } if ("$endsWith" in fields) { for (const [key, value] of Object.entries(fields["$endsWith"])) { if (typeof obj[key] !== "string" || !obj[key].endsWith(value)) return false; } } return true; } function checkBetween(obj, fields) { if ("$between" in fields) { for (const [key, [min, max]] of Object.entries(fields["$between"])) { if (typeof obj[key] !== "number" || obj[key] < min || obj[key] > max) return false; } } return true; } function checkNot(obj, fields) { if ("$not" in fields) { return !hasFieldsAdvanced(obj, fields["$not"]); } return true; } function checkSubset(obj, fields) { if ("$subset" in fields) { const setFields = fields["$subset"]; return hasFields(obj, setFields); } return true; }