UNPKG

tinycoll

Version:

A minimal reactive document store with Mongo-like querying, reactivity, TTL support, and optional persistence.

113 lines (112 loc) 3.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.applyModifier = applyModifier; function getValue(obj, path) { return path.split('.').reduce((o, k) => o?.[k], obj); } function setValue(obj, path, value) { const keys = path.split('.'); const last = keys.pop(); let updated = structuredClone(obj); let target = updated; for (const k of keys) { target[k] = structuredClone(target[k] ?? {}); target = target[k]; } target[last] = value; return updated; } function unsetValue(obj, path) { const keys = path.split('.'); const last = keys.pop(); let updated = structuredClone(obj); let parent = updated; for (const k of keys) { parent[k] = structuredClone(parent[k] ?? {}); parent = parent[k]; } delete parent[last]; return updated; } function applyModifier(doc, mod, ctx = {}) { let updated = doc; if (mod.$setOnInsert && ctx.inserting) { for (const [k, v] of Object.entries(mod.$setOnInsert)) { if (getValue(updated, k) === undefined) { updated = setValue(updated, k, v); } } } if (mod.$set) { for (const [k, v] of Object.entries(mod.$set)) { const current = getValue(updated, k); if (current !== v) updated = setValue(updated, k, v); } } if (mod.$inc) { for (const [k, v] of Object.entries(mod.$inc)) { const current = getValue(updated, k); updated = setValue(updated, k, (typeof current === 'number' ? current : 0) + v); } } if (mod.$min) { for (const [k, v] of Object.entries(mod.$min)) { const current = getValue(updated, k); if (typeof current === 'number' && typeof v === 'number') { if (v < current) updated = setValue(updated, k, v); } } } if (mod.$max) { for (const [k, v] of Object.entries(mod.$max)) { const current = getValue(updated, k); if (typeof current === 'number' && typeof v === 'number') { if (v > current) updated = setValue(updated, k, v); } } } if (mod.$mul) { for (const [k, v] of Object.entries(mod.$mul)) { const current = getValue(updated, k); updated = setValue(updated, k, (typeof current === 'number' ? current : 0) * v); } } if (mod.$unset) { for (const k of Object.keys(mod.$unset)) { if (getValue(updated, k) !== undefined) { updated = unsetValue(updated, k); } } } if (mod.$push) { for (const [k, v] of Object.entries(mod.$push)) { const arr = getValue(updated, k); updated = setValue(updated, k, Array.isArray(arr) ? [...arr, v] : [v]); } } if (mod.$addToSet) { for (const [k, v] of Object.entries(mod.$addToSet)) { const arr = getValue(updated, k); if (Array.isArray(arr)) { if (!arr.includes(v)) { updated = setValue(updated, k, [...arr, v]); } } else { updated = setValue(updated, k, [v]); } } } if (mod.$pull) { for (const [k, v] of Object.entries(mod.$pull)) { const arr = getValue(updated, k); if (Array.isArray(arr)) { updated = setValue(updated, k, arr.filter((item) => item !== v)); } } } return updated; }