blob: fb579cb0c6c0579377108814e312fd81b54f120c [file] [log] [blame]
import { upsert } from 'pouchdb-utils';
import { stringMd5 } from 'pouchdb-md5';
import createViewSignature from './createViewSignature';
function createView(sourceDB, viewName, mapFun, reduceFun, temporary, localDocName) {
var viewSignature = createViewSignature(mapFun, reduceFun);
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/' + localDocName, 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;