(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PouchUpsert = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
        'use strict';

        var PouchPromise = require('pouchdb-promise');

// this is essentially the "update sugar" function from daleharvey/pouchdb#1388
// the diffFun tells us what delta to apply to the doc.  it either returns
// the doc, or false if it doesn't need to do an update after all
        function upsertInner(db, docId, diffFun) {
            if (typeof docId !== 'string') {
                return PouchPromise.reject(new Error('doc id is required'));
            }

            return db.get(docId)["catch"](function (err) {
                /* istanbul ignore next */
                if (err.status !== 404) {
                    throw err;
                }
                return {};
            }).then(function (doc) {
                // the user might change the _rev, so save it for posterity
                var docRev = doc._rev;
                var newDoc = diffFun(doc);

                if (!newDoc) {
                    // if the diffFun returns falsy, we short-circuit as
                    // an optimization
                    return { updated: false, rev: docRev, id: docId };
                }

                // users aren't allowed to modify these values,
                // so reset them here
                newDoc._id = docId;
                newDoc._rev = docRev;
                return tryAndPut(db, newDoc, diffFun);
            });
        }

        function tryAndPut(db, doc, diffFun) {
            return db.put(doc).then(function (res) {
                return {
                    updated: true,
                    rev: res.rev,
                    id: doc._id
                };
            }, function (err) {
                /* istanbul ignore next */
                if (err.status !== 409) {
                    throw err;
                }
                return upsertInner(db, doc._id, diffFun);
            });
        }

        exports.upsert = function upsert(docId, diffFun, cb) {
            var db = this;
            var promise = upsertInner(db, docId, diffFun);
            if (typeof cb !== 'function') {
                return promise;
            }
            promise.then(function (resp) {
                cb(null, resp);
            }, cb);
        };

        exports.putIfNotExists = function putIfNotExists(docId, doc, cb) {
            var db = this;

            if (typeof docId !== 'string') {
                cb = doc;
                doc = docId;
                docId = doc._id;
            }

            var diffFun = function (existingDoc) {
                if (existingDoc._rev) {
                    return false; // do nothing
                }
                return doc;
            };

            var promise = upsertInner(db, docId, diffFun);
            if (typeof cb !== 'function') {
                return promise;
            }
            promise.then(function (resp) {
                cb(null, resp);
            }, cb);
        };


        /* istanbul ignore next */
        if (typeof window !== 'undefined' && window.PouchDB) {
            window.PouchDB.plugin(exports);
        }

    },{"pouchdb-promise":4}],2:[function(require,module,exports){
        (function (global){
            'use strict';
            var Mutation = global.MutationObserver || global.WebKitMutationObserver;

            var scheduleDrain;

            {
                if (Mutation) {
                    var called = 0;
                    var observer = new Mutation(nextTick);
                    var element = global.document.createTextNode('');
                    observer.observe(element, {
                        characterData: true
                    });
                    scheduleDrain = function () {
                        element.data = (called = ++called % 2);
                    };
                } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
                    var channel = new global.MessageChannel();
                    channel.port1.onmessage = nextTick;
                    scheduleDrain = function () {
                        channel.port2.postMessage(0);
                    };
                } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
                    scheduleDrain = function () {

                        // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
                        // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
                        var scriptEl = global.document.createElement('script');
                        scriptEl.onreadystatechange = function () {
                            nextTick();

                            scriptEl.onreadystatechange = null;
                            scriptEl.parentNode.removeChild(scriptEl);
                            scriptEl = null;
                        };
                        global.document.documentElement.appendChild(scriptEl);
                    };
                } else {
                    scheduleDrain = function () {
                        setTimeout(nextTick, 0);
                    };
                }
            }

            var draining;
            var queue = [];
//named nextTick for less confusing stack traces
            function nextTick() {
                draining = true;
                var i, oldQueue;
                var len = queue.length;
                while (len) {
                    oldQueue = queue;
                    queue = [];
                    i = -1;
                    while (++i < len) {
                        oldQueue[i]();
                    }
                    len = queue.length;
                }
                draining = false;
            }

            module.exports = immediate;
            function immediate(task) {
                if (queue.push(task) === 1 && !draining) {
                    scheduleDrain();
                }
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    },{}],3:[function(require,module,exports){
        'use strict';
        var immediate = require('immediate');

        /* istanbul ignore next */
        function INTERNAL() {}

        var handlers = {};

        var REJECTED = ['REJECTED'];
        var FULFILLED = ['FULFILLED'];
        var PENDING = ['PENDING'];

        module.exports = Promise;

        function Promise(resolver) {
            if (typeof resolver !== 'function') {
                throw new TypeError('resolver must be a function');
            }
            this.state = PENDING;
            this.queue = [];
            this.outcome = void 0;
            if (resolver !== INTERNAL) {
                safelyResolveThenable(this, resolver);
            }
        }

        Promise.prototype["catch"] = function (onRejected) {
            return this.then(null, onRejected);
        };
        Promise.prototype.then = function (onFulfilled, onRejected) {
            if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
                typeof onRejected !== 'function' && this.state === REJECTED) {
                return this;
            }
            var promise = new this.constructor(INTERNAL);
            if (this.state !== PENDING) {
                var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
                unwrap(promise, resolver, this.outcome);
            } else {
                this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
            }

            return promise;
        };
        function QueueItem(promise, onFulfilled, onRejected) {
            this.promise = promise;
            if (typeof onFulfilled === 'function') {
                this.onFulfilled = onFulfilled;
                this.callFulfilled = this.otherCallFulfilled;
            }
            if (typeof onRejected === 'function') {
                this.onRejected = onRejected;
                this.callRejected = this.otherCallRejected;
            }
        }
        QueueItem.prototype.callFulfilled = function (value) {
            handlers.resolve(this.promise, value);
        };
        QueueItem.prototype.otherCallFulfilled = function (value) {
            unwrap(this.promise, this.onFulfilled, value);
        };
        QueueItem.prototype.callRejected = function (value) {
            handlers.reject(this.promise, value);
        };
        QueueItem.prototype.otherCallRejected = function (value) {
            unwrap(this.promise, this.onRejected, value);
        };

        function unwrap(promise, func, value) {
            immediate(function () {
                var returnValue;
                try {
                    returnValue = func(value);
                } catch (e) {
                    return handlers.reject(promise, e);
                }
                if (returnValue === promise) {
                    handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
                } else {
                    handlers.resolve(promise, returnValue);
                }
            });
        }

        handlers.resolve = function (self, value) {
            var result = tryCatch(getThen, value);
            if (result.status === 'error') {
                return handlers.reject(self, result.value);
            }
            var thenable = result.value;

            if (thenable) {
                safelyResolveThenable(self, thenable);
            } else {
                self.state = FULFILLED;
                self.outcome = value;
                var i = -1;
                var len = self.queue.length;
                while (++i < len) {
                    self.queue[i].callFulfilled(value);
                }
            }
            return self;
        };
        handlers.reject = function (self, error) {
            self.state = REJECTED;
            self.outcome = error;
            var i = -1;
            var len = self.queue.length;
            while (++i < len) {
                self.queue[i].callRejected(error);
            }
            return self;
        };

        function getThen(obj) {
            // Make sure we only access the accessor once as required by the spec
            var then = obj && obj.then;
            if (obj && typeof obj === 'object' && typeof then === 'function') {
                return function appyThen() {
                    then.apply(obj, arguments);
                };
            }
        }

        function safelyResolveThenable(self, thenable) {
            // Either fulfill, reject or reject with error
            var called = false;
            function onError(value) {
                if (called) {
                    return;
                }
                called = true;
                handlers.reject(self, value);
            }

            function onSuccess(value) {
                if (called) {
                    return;
                }
                called = true;
                handlers.resolve(self, value);
            }

            function tryToUnwrap() {
                thenable(onSuccess, onError);
            }

            var result = tryCatch(tryToUnwrap);
            if (result.status === 'error') {
                onError(result.value);
            }
        }

        function tryCatch(func, value) {
            var out = {};
            try {
                out.value = func(value);
                out.status = 'success';
            } catch (e) {
                out.status = 'error';
                out.value = e;
            }
            return out;
        }

        Promise.resolve = resolve;
        function resolve(value) {
            if (value instanceof this) {
                return value;
            }
            return handlers.resolve(new this(INTERNAL), value);
        }

        Promise.reject = reject;
        function reject(reason) {
            var promise = new this(INTERNAL);
            return handlers.reject(promise, reason);
        }

        Promise.all = all;
        function all(iterable) {
            var self = this;
            if (Object.prototype.toString.call(iterable) !== '[object Array]') {
                return this.reject(new TypeError('must be an array'));
            }

            var len = iterable.length;
            var called = false;
            if (!len) {
                return this.resolve([]);
            }

            var values = new Array(len);
            var resolved = 0;
            var i = -1;
            var promise = new this(INTERNAL);

            while (++i < len) {
                allResolver(iterable[i], i);
            }
            return promise;
            function allResolver(value, i) {
                self.resolve(value).then(resolveFromAll, function (error) {
                    if (!called) {
                        called = true;
                        handlers.reject(promise, error);
                    }
                });
                function resolveFromAll(outValue) {
                    values[i] = outValue;
                    if (++resolved === len && !called) {
                        called = true;
                        handlers.resolve(promise, values);
                    }
                }
            }
        }

        Promise.race = race;
        function race(iterable) {
            var self = this;
            if (Object.prototype.toString.call(iterable) !== '[object Array]') {
                return this.reject(new TypeError('must be an array'));
            }

            var len = iterable.length;
            var called = false;
            if (!len) {
                return this.resolve([]);
            }

            var i = -1;
            var promise = new this(INTERNAL);

            while (++i < len) {
                resolver(iterable[i]);
            }
            return promise;
            function resolver(value) {
                self.resolve(value).then(function (response) {
                    if (!called) {
                        called = true;
                        handlers.resolve(promise, response);
                    }
                }, function (error) {
                    if (!called) {
                        called = true;
                        handlers.reject(promise, error);
                    }
                });
            }
        }

    },{"immediate":2}],4:[function(require,module,exports){
        'use strict';

        function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

        var lie = _interopDefault(require('lie'));

        /* istanbul ignore next */
        var PouchPromise = typeof Promise === 'function' ? Promise : lie;

        module.exports = PouchPromise;

    },{"lie":3}]},{},[1])(1)
});
