UNPKG

zumito-db

Version:

Multi-driver database abstraction layer with decorator-based models

143 lines (142 loc) 4.85 kB
import { mkdirSync } from 'fs'; export class TingoDriver { db; raw; async connect(config) { mkdirSync(config.path || './db/tingodb', { recursive: true }); try { // @ts-ignore - optional peer dependency const tingoModule = await import('tingodb'); const factory = tingoModule.default || tingoModule; const tingodb = typeof factory === 'function' ? factory() : new factory.Db(config.path || './db/tingodb', {}); const Db = tingodb.Db || factory.Db; this.db = new Db(config.path || './db/tingodb', {}); this.raw = this.db; } catch { const { createRequire } = await import('module'); const req = createRequire(import.meta.url); // @ts-ignore - optional peer dependency const tingodb = req('tingodb')(); this.db = new tingodb.Db(config.path || './db/tingodb', {}); this.raw = this.db; } } async disconnect() { } async find(collection, query) { return new Promise((resolve, reject) => { const filter = this.buildFilter(query); const cursor = this.db.collection(collection).find(filter); if (query.select) { const projection = {}; for (const f of query.select) projection[f] = 1; cursor.project(projection); } if (query.sort) { const sort = {}; for (const s of query.sort) sort[s.field] = s.dir === 'asc' ? 1 : -1; cursor.sort(sort); } if (query.offset) cursor.skip(query.offset); if (query.limit) cursor.limit(query.limit); cursor.toArray((err, docs) => { if (err) reject(err); else resolve(docs || []); }); }); } async findOne(collection, query) { return new Promise((resolve, reject) => { this.db.collection(collection).findOne(this.buildFilter(query), (err, doc) => { if (err) reject(err); else resolve(doc || null); }); }); } async insert(collection, data) { return new Promise((resolve, reject) => { this.db.collection(collection).insert(data, (err, docs) => { if (err) reject(err); else resolve(docs[0]); }); }); } async update(collection, query, data) { return new Promise((resolve, reject) => { this.db.collection(collection).update(this.buildFilter(query), { $set: data }, { multi: true }, (err, count) => { if (err) reject(err); else resolve(count); }); }); } async delete(collection, query) { return new Promise((resolve, reject) => { this.db.collection(collection).remove(this.buildFilter(query), (err, count) => { if (err) reject(err); else resolve(count); }); }); } async count(collection, query) { return new Promise((resolve, reject) => { this.db.collection(collection).count(this.buildFilter(query), (err, count) => { if (err) reject(err); else resolve(count); }); }); } async ensureSchema(_metadata) { } async dropCollection(name) { return new Promise((resolve, reject) => { this.db.dropCollection(name, (err) => { if (err) reject(err); else resolve(); }); }); } async listCollections() { return new Promise((resolve, reject) => { this.db.collections((err, names) => { if (err) reject(err); else resolve(names || []); }); }); } buildFilter(query) { if (!query.where || query.where.length === 0) return {}; const filter = {}; for (const clause of query.where) { if (clause.operator === 'eq') { filter[clause.field] = clause.value; } else if (clause.operator === 'like') { filter[clause.field] = { $regex: clause.value }; } else { filter[clause.field] = { ['$' + clause.operator]: clause.value }; } } return filter; } }