import { LiveArray } from './livearray.js'; import { isObject } from './utils.js'; export function PouchORM(PouchDB) { PouchDB.registerType = (name, cls, db) => { const prefix = name.toLowerCase(); const _db = db || PouchDB(prefix); _db.setMaxListeners(1000); const _baseSelector = Object.freeze({ _id: { $gt: `${prefix}_0`, $lt: `${prefix}_\ufff0` } }); const watch = Watcher(_db, _baseSelector, { include_docs: true }); if (!cls.hasOwnProperty('validate')) { warn(`${cls.name} has no validation.`); } const instantiate = doc => new cls(doc); async function find(idOrSelector, opts = {}) { if (typeof idOrSelector === 'string') { return instantiate(await _db.get(idOrSelector)); } const isSelector = isObject(idOrSelector); const selector = Object.assign( isSelector && idOrSelector._deleted ? { _deleted: true } : { _deleted: { exists: false } }, isSelector ? idOrSelector : _baseSelector ); if (opts.index) { opts.use_index = [prefix, opts.index]; delete opts.index; } if (opts.live) { opts.mapper = instantiate; return LiveArray(_db, idOrSelector, opts); } return (await _db.find(Object.assign({ selector: idOrSelector }, opts))).docs.map(instantiate); } async function getOrCreate(props) { let doc = await new cls(props); try { await doc.save(); } catch (e) { if (e.status !== 409) { throw e; } doc = await find(doc._id); } return doc; } async function _delete(id) { try { const doc = await find(id); doc._deleted = true; await _db.put(doc); } catch (e) { if (e.status !== 404) { throw e; } } } async function _index(name, fields) { return _db.createIndex({ index: { ddoc: prefix, fields, name } }); } Object.defineProperties(cls.prototype, { _name: { value: name }, _prefix: { value: prefix }, _db: { value: _db }, _cls: { value: cls }, _baseSelector: { value: _baseSelector } }); Object.defineProperties(cls, { getOrCreate: { value: getOrCreate }, find: { value: find }, index: { value: _index }, delete: { value: _delete }, subscribe: { value: watch }, db: { value: _db }, name: { value: name }, prefix: { value: prefix }, selector: { value: _baseSelector } }); return cls; }; }