UNPKG

ryuudb

Version:

A lightweight, customizable JSON/YAML database for Node.js by Jr Busaco

110 lines (97 loc) 3.09 kB
import { FileAdapter } from './adapters/file.js'; import { MemoryAdapter } from './adapters/memory.js'; import { EventEmitter } from 'events'; export default class RyuuDB extends EventEmitter { constructor(options = {}) { super(); this.options = { filePath: 'db.json', format: 'json', adapter: 'file', debounce: 100, defaultData: {}, ...options }; this.data = this.options.defaultData; this.adapter = this._createAdapter(); this.timeout = null; this.load(); } _createAdapter() { if (typeof this.options.adapter === 'object') return this.options.adapter; if (this.options.adapter === 'memory') return new MemoryAdapter(); return new FileAdapter(this.options.filePath, this.options.format); } async load() { this.data = await this.adapter.read() || this.options.defaultData; this.emit('load', this.data); } async save() { await this.adapter.write(this.data); this.emit('save', this.data); } debounceSave() { clearTimeout(this.timeout); this.timeout = setTimeout(() => this.save(), this.options.debounce); } get(path) { if (!path) return this.data; return path.split('.').reduce((obj, key) => obj?.[key], this.data); } set(path, value) { let obj = this.data; const keys = path.split('.'); for (let i = 0; i < keys.length - 1; i++) { obj = obj[keys[i]] = obj[keys[i]] || {}; } obj[keys[keys.length - 1]] = value; this.debounceSave(); this.emit('set', { path, value }); return this; } find(path, query) { const arr = this.get(path); if (!Array.isArray(arr)) return null; if (typeof query === 'function') return arr.find(query); return arr.find(item => Object.entries(query).every(([k, v]) => item[k] === v)) || null; } filter(path, query) { const arr = this.get(path); if (!Array.isArray(arr)) return []; if (typeof query === 'function') return arr.filter(query); return arr.filter(item => Object.entries(query).every(([k, v]) => item[k] === v)); } update(path, query, updates) { const arr = this.get(path); if (!Array.isArray(arr)) return this; const index = typeof query === 'function' ? arr.findIndex(query) : arr.findIndex(item => Object.entries(query).every(([k, v]) => item[k] === v)); if (index >= 0) { arr[index] = { ...arr[index], ...updates }; this.set(path, arr); this.emit('update', { path, index, updates }); } return this; } remove(path, query) { const arr = this.get(path); if (!Array.isArray(arr)) return this; const filtered = typeof query === 'function' ? arr.filter(item => !query(item)) : arr.filter(item => !Object.entries(query).every(([k, v]) => item[k] === v)); this.set(path, filtered); this.emit('remove', { path, query }); return this; } clear(path) { if (path) { this.set(path, {}); } else { this.data = this.options.defaultData; this.debounceSave(); } this.emit('clear', { path }); return this; } }