UNPKG

wise-json-db

Version:

Blazing fast, crash-proof embedded JSON database for Node.js with batch operations, TTL, indexes, and segmented checkpointing.

170 lines (156 loc) 6.38 kB
/** * wise-json/collection/utils.js * Утилиты для работы с коллекциями WiseJSON (id, типы, сериализация и др.) */ /** * Генерирует уникальный id (короткий, простой). * @returns {string} */ function defaultIdGenerator() { return Math.random().toString(36).slice(2, 10) + Date.now().toString(36); } /** * Проверяет, является ли значение непустой строкой. * @param {any} value * @returns {boolean} */ function isNonEmptyString(value) { return typeof value === 'string' && value.length > 0; } /** * Проверяет, является ли значение plain-объектом (без прототипа). * @param {any} value * @returns {boolean} */ function isPlainObject(value) { return Object.prototype.toString.call(value) === '[object Object]'; } /** * Делает абсолютный путь (удобно для базы) * @param {string} p * @returns {string} */ function makeAbsolutePath(p) { return require('path').isAbsolute(p) ? p : require('path').resolve(process.cwd(), p); } /** * Валидирует/дополняет опции коллекции. * @param {object} [opts] * @returns {object} */ function validateOptions(opts = {}) { return Object.assign({ maxSegmentSizeBytes: 2 * 1024 * 1024, checkpointIntervalMs: 60000, ttlCleanupIntervalMs: 60000, walSync: false }, opts || {}); } /** * Преобразует массив документов в CSV-строку. * @param {Array<Object>} docs * @returns {string} */ function flattenDocToCsv(docs) { if (!Array.isArray(docs) || docs.length === 0) return ''; const fields = Array.from(new Set(docs.flatMap(doc => Object.keys(doc)))); const escape = v => (typeof v === 'string' && (v.includes(',') || v.includes('"') || v.includes('\n'))) ? `"${String(v).replace(/"/g, '""')}"` : v; const csv = [ fields.join(','), ...docs.map(doc => fields.map(f => escape(doc[f] ?? '')).join(',')) ]; return csv.join('\n'); } /** * Проверяет, соответствует ли документ декларативному фильтру (в стиле MongoDB). * @param {object} doc - Документ для проверки. * @param {object} filter - Объект фильтра. * @returns {boolean} */ function matchFilter(doc, filter) { if (typeof filter !== 'object' || filter == null || doc === null || typeof doc !== 'object') { return false; } if (Array.isArray(filter.$or)) { return filter.$or.some(f => matchFilter(doc, f)); } if (Array.isArray(filter.$and)) { return filter.$and.every(f => matchFilter(doc, f)); } for (const key of Object.keys(filter)) { if (key === '$or' || key === '$and') continue; const cond = filter[key]; const value = doc[key]; if (typeof cond === 'object' && cond !== null && !Array.isArray(cond)) { for (const op of Object.keys(cond)) { const opVal = cond[op]; let match = true; switch (op) { case '$gt': if (!(value > opVal)) match = false; break; case '$gte': if (!(value >= opVal)) match = false; break; case '$lt': if (!(value < opVal)) match = false; break; case '$lte': if (!(value <= opVal)) match = false; break; case '$ne': if (value === opVal) match = false; break; // --- ИЗМЕНЕНИЕ ЗДЕСЬ --- case '$in': { if (!Array.isArray(opVal)) { match = false; } else if (Array.isArray(value)) { // Если поле в документе - массив, проверяем пересечение match = value.some(item => opVal.includes(item)); } else { // Если поле в документе - простое значение match = opVal.includes(value); } break; } case '$nin': { if (!Array.isArray(opVal)) { match = false; } else if (Array.isArray(value)) { // Если поле в документе - массив, проверяем отсутствие пересечений match = !value.some(item => opVal.includes(item)); } else { // Если поле в документе - простое значение match = !opVal.includes(value); } break; } // --- КОНЕЦ ИЗМЕНЕНИЯ --- case '$exists': if ((value !== undefined) !== opVal) match = false; break; case '$regex': { if (typeof value !== 'string') { match = false; } else { try { const re = new RegExp(opVal, cond.$options || ''); if (!re.test(value)) match = false; } catch (e) { match = false; } } break; } default: match = false; break; } if (!match) return false; } } else { if (value !== cond) return false; } } return true; } module.exports = { defaultIdGenerator, isNonEmptyString, isPlainObject, makeAbsolutePath, validateOptions, flattenDocToCsv, matchFilter, };