| 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; |