UNPKG

pouchdb-mapreduce

Version:

PouchDB's map/reduce query API as a plugin.

82 lines (73 loc) 2.5 kB
import { upsert } from 'pouchdb-utils'; import { stringMd5 } from 'pouchdb-md5'; function createView(opts) { var sourceDB = opts.db; var viewName = opts.viewName; var mapFun = opts.map; var reduceFun = opts.reduce; var temporary = opts.temporary; // the "undefined" part is for backwards compatibility var viewSignature = mapFun.toString() + (reduceFun && reduceFun.toString()) + 'undefined'; var cachedViews; if (!temporary) { // cache this to ensure we don't try to update the same view twice cachedViews = sourceDB._cachedViews = sourceDB._cachedViews || {}; if (cachedViews[viewSignature]) { return cachedViews[viewSignature]; } } var promiseForView = sourceDB.info().then(function (info) { var depDbName = info.db_name + '-mrview-' + (temporary ? 'temp' : stringMd5(viewSignature)); // save the view name in the source db so it can be cleaned up if necessary // (e.g. when the _design doc is deleted, remove all associated view data) function diffFunction(doc) { doc.views = doc.views || {}; var fullViewName = viewName; if (fullViewName.indexOf('/') === -1) { fullViewName = viewName + '/' + viewName; } var depDbs = doc.views[fullViewName] = doc.views[fullViewName] || {}; /* istanbul ignore if */ if (depDbs[depDbName]) { return; // no update necessary } depDbs[depDbName] = true; return doc; } return upsert(sourceDB, '_local/mrviews', diffFunction).then(function () { return sourceDB.registerDependentDatabase(depDbName).then(function (res) { var db = res.db; db.auto_compaction = true; var view = { name: depDbName, db: db, sourceDB: sourceDB, adapter: sourceDB.adapter, mapFun: mapFun, reduceFun: reduceFun }; return view.db.get('_local/lastSeq').catch(function (err) { /* istanbul ignore if */ if (err.status !== 404) { throw err; } }).then(function (lastSeqDoc) { view.seq = lastSeqDoc ? lastSeqDoc.seq : 0; if (cachedViews) { view.db.once('destroyed', function () { delete cachedViews[viewSignature]; }); } return view; }); }); }); }); if (cachedViews) { cachedViews[viewSignature] = promiseForView; } return promiseForView; } export default createView;