| "use strict"; |
| |
| var PouchDB = require("./constructor"); |
| var utils = require('./utils'); |
| var Promise = utils.Promise; |
| var EventEmitter = require('events').EventEmitter; |
| PouchDB.adapters = {}; |
| PouchDB.preferredAdapters = require('./adapters/preferredAdapters.js'); |
| |
| PouchDB.prefix = '_pouch_'; |
| |
| var eventEmitter = new EventEmitter(); |
| |
| var eventEmitterMethods = [ |
| 'on', |
| 'addListener', |
| 'emit', |
| 'listeners', |
| 'once', |
| 'removeAllListeners', |
| 'removeListener', |
| 'setMaxListeners' |
| ]; |
| |
| eventEmitterMethods.forEach(function (method) { |
| PouchDB[method] = eventEmitter[method].bind(eventEmitter); |
| }); |
| PouchDB.setMaxListeners(0); |
| PouchDB.parseAdapter = function (name, opts) { |
| var match = name.match(/([a-z\-]*):\/\/(.*)/); |
| var adapter, adapterName; |
| if (match) { |
| // the http adapter expects the fully qualified name |
| name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2]; |
| adapter = match[1]; |
| if (!PouchDB.adapters[adapter].valid()) { |
| throw 'Invalid adapter'; |
| } |
| return {name: name, adapter: match[1]}; |
| } |
| |
| // check for browsers that have been upgraded from websql-only to websql+idb |
| var skipIdb = 'idb' in PouchDB.adapters && 'websql' in PouchDB.adapters && |
| utils.hasLocalStorage() && |
| localStorage['_pouch__websqldb_' + PouchDB.prefix + name]; |
| |
| if (typeof opts !== 'undefined' && opts.db) { |
| adapterName = 'leveldb'; |
| } else { |
| for (var i = 0; i < PouchDB.preferredAdapters.length; ++i) { |
| adapterName = PouchDB.preferredAdapters[i]; |
| if (adapterName in PouchDB.adapters) { |
| if (skipIdb && adapterName === 'idb') { |
| continue; // keep using websql to avoid user data loss |
| } |
| break; |
| } |
| } |
| } |
| |
| adapter = PouchDB.adapters[adapterName]; |
| if (adapterName && adapter) { |
| var use_prefix = 'use_prefix' in adapter ? adapter.use_prefix : true; |
| |
| return { |
| name: use_prefix ? PouchDB.prefix + name : name, |
| adapter: adapterName |
| }; |
| } |
| |
| throw 'No valid adapter found'; |
| }; |
| |
| PouchDB.destroy = utils.toPromise(function (name, opts, callback) { |
| |
| if (typeof opts === 'function' || typeof opts === 'undefined') { |
| callback = opts; |
| opts = {}; |
| } |
| if (name && typeof name === 'object') { |
| opts = name; |
| name = undefined; |
| } |
| |
| if (!opts.internal) { |
| console.log('PouchDB.destroy() is deprecated and will be removed. ' + |
| 'Please use db.destroy() instead.'); |
| } |
| |
| var backend = PouchDB.parseAdapter(opts.name || name, opts); |
| var dbName = backend.name; |
| var adapter = PouchDB.adapters[backend.adapter]; |
| var usePrefix = 'use_prefix' in adapter ? adapter.use_prefix : true; |
| var baseName = usePrefix ? |
| dbName.replace(new RegExp('^' + PouchDB.prefix), '') : dbName; |
| var fullName = (backend.adapter === 'http' || backend.adapter === 'https' ? |
| '' : (opts.prefix || '')) + dbName; |
| function destroyDb() { |
| // call destroy method of the particular adaptor |
| adapter.destroy(fullName, opts, function (err, resp) { |
| if (err) { |
| callback(err); |
| } else { |
| PouchDB.emit('destroyed', name); |
| //so we don't have to sift through all dbnames |
| PouchDB.emit(name, 'destroyed'); |
| callback(null, resp || { 'ok': true }); |
| } |
| }); |
| } |
| |
| var createOpts = utils.extend(true, {}, opts, {adapter : backend.adapter}); |
| new PouchDB(baseName, createOpts, function (err, db) { |
| if (err) { |
| return callback(err); |
| } |
| db.get('_local/_pouch_dependentDbs', function (err, localDoc) { |
| if (err) { |
| if (err.status !== 404) { |
| return callback(err); |
| } else { // no dependencies |
| return destroyDb(); |
| } |
| } |
| var dependentDbs = localDoc.dependentDbs; |
| var deletedMap = Object.keys(dependentDbs).map(function (name) { |
| var trueName = usePrefix ? |
| name.replace(new RegExp('^' + PouchDB.prefix), '') : name; |
| var subOpts = utils.extend(true, opts, db.__opts || {}); |
| return db.constructor.destroy(trueName, subOpts); |
| }); |
| Promise.all(deletedMap).then(destroyDb, function (error) { |
| callback(error); |
| }); |
| }); |
| }); |
| }); |
| |
| PouchDB.adapter = function (id, obj) { |
| if (obj.valid()) { |
| PouchDB.adapters[id] = obj; |
| } |
| }; |
| |
| PouchDB.plugin = function (obj) { |
| Object.keys(obj).forEach(function (id) { |
| PouchDB.prototype[id] = obj[id]; |
| }); |
| }; |
| |
| PouchDB.defaults = function (defaultOpts) { |
| function PouchAlt(name, opts, callback) { |
| if (typeof opts === 'function' || typeof opts === 'undefined') { |
| callback = opts; |
| opts = {}; |
| } |
| if (name && typeof name === 'object') { |
| opts = name; |
| name = undefined; |
| } |
| |
| opts = utils.extend(true, {}, defaultOpts, opts); |
| PouchDB.call(this, name, opts, callback); |
| } |
| |
| utils.inherits(PouchAlt, PouchDB); |
| |
| PouchAlt.destroy = utils.toPromise(function (name, opts, callback) { |
| if (typeof opts === 'function' || typeof opts === 'undefined') { |
| callback = opts; |
| opts = {}; |
| } |
| |
| if (name && typeof name === 'object') { |
| opts = name; |
| name = undefined; |
| } |
| opts = utils.extend(true, {}, defaultOpts, opts); |
| return PouchDB.destroy(name, opts, callback); |
| }); |
| |
| eventEmitterMethods.forEach(function (method) { |
| PouchAlt[method] = eventEmitter[method].bind(eventEmitter); |
| }); |
| PouchAlt.setMaxListeners(0); |
| |
| PouchAlt.preferredAdapters = PouchDB.preferredAdapters.slice(); |
| Object.keys(PouchDB).forEach(function (key) { |
| if (!(key in PouchAlt)) { |
| PouchAlt[key] = PouchDB[key]; |
| } |
| }); |
| |
| return PouchAlt; |
| }; |
| |
| module.exports = PouchDB; |