UNPKG

pouchdb-find

Version:
98 lines (89 loc) 3.02 kB
'use strict'; var upsert = require('./upsert'); var utils = require('./utils'); var Promise = utils.Promise; function stringify(input) { if (!input) { return 'undefined'; // backwards compat for empty reduce } // for backwards compat with mapreduce, functions/strings are stringified // as-is. everything else is JSON-stringified. switch (typeof input) { case 'function': // e.g. a mapreduce map return input.toString(); case 'string': // e.g. a mapreduce built-in _reduce function return input.toString(); default: // e.g. a JSON object in the case of mango queries return JSON.stringify(input); } } module.exports = function (opts) { var sourceDB = opts.db; var viewName = opts.viewName; var mapFun = opts.map; var reduceFun = opts.reduce; var temporary = opts.temporary; var pluginName = opts.pluginName; // the "undefined" part is for backwards compatibility var viewSignature = stringify(mapFun) + stringify(reduceFun) + 'undefined'; if (!temporary && sourceDB._cachedViews) { var cachedView = sourceDB._cachedViews[viewSignature]; if (cachedView) { return Promise.resolve(cachedView); } } return sourceDB.info().then(function (info) { var depDbName = info.db_name + '-mrview-' + (temporary ? 'temp' : utils.MD5(viewSignature)); // save the view name in the source PouchDB 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/' + pluginName, 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 (!temporary) { sourceDB._cachedViews = sourceDB._cachedViews || {}; sourceDB._cachedViews[viewSignature] = view; view.db.on('destroyed', function () { delete sourceDB._cachedViews[viewSignature]; }); } return view; }); }); }); }); };