text: "use strict";
  
  exports.__esModule = true;
  exports.default = void 0;
  
  var _lodash = _interopRequireDefault(require("lodash.merge"));
  
  var _util = _interopRequireDefault(require("../util"));
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  Function.prototype.$asyncbind = function $asyncbind(self, catcher) {
    "use strict";
  
    if (!Function.prototype.$asyncbind) {
      Object.defineProperty(Function.prototype, "$asyncbind", {
        value: $asyncbind,
        enumerable: false,
        configurable: true,
        writable: true
      });
    }
  
    if (!$asyncbind.trampoline) {
      $asyncbind.trampoline = function trampoline(t, x, s, e, u) {
        return function b(q) {
          while (q) {
            if (q.then) {
              q = q.then(b, e);
              return u ? undefined : q;
            }
  
            try {
              if (q.pop) {
                if (q.length) return q.pop() ? x.call(t) : q;
                q = s;
              } else q = q.call(t);
            } catch (r) {
              return e(r);
            }
          }
        };
      };
    }
  
    if (!$asyncbind.LazyThenable) {
      $asyncbind.LazyThenable = function () {
        function isThenable(obj) {
          return obj && obj instanceof Object && typeof obj.then === "function";
        }
  
        function resolution(p, r, how) {
          try {
            var x = how ? how(r) : r;
            if (p === x) return p.reject(new TypeError("Promise resolution loop"));
  
            if (isThenable(x)) {
              x.then(function (y) {
                resolution(p, y);
              }, function (e) {
                p.reject(e);
              });
            } else {
              p.resolve(x);
            }
          } catch (ex) {
            p.reject(ex);
          }
        }
  
        function _unchained(v) {}
  
        function thenChain(res, rej) {
          this.resolve = res;
          this.reject = rej;
        }
  
        function Chained() {}
  
        ;
        Chained.prototype = {
          resolve: _unchained,
          reject: _unchained,
          then: thenChain
        };
  
        function then(res, rej) {
          var chain = new Chained();
  
          try {
            this._resolver(function (value) {
              return isThenable(value) ? value.then(res, rej) : resolution(chain, value, res);
            }, function (ex) {
              resolution(chain, ex, rej);
            });
          } catch (ex) {
            resolution(chain, ex, rej);
          }
  
          return chain;
        }
  
        function Thenable(resolver) {
          this._resolver = resolver;
          this.then = then;
        }
  
        ;
  
        Thenable.resolve = function (v) {
          return Thenable.isThenable(v) ? v : {
            then: function then(resolve) {
              return resolve(v);
            }
          };
        };
  
        Thenable.isThenable = isThenable;
        return Thenable;
      }();
  
      $asyncbind.EagerThenable = $asyncbind.Thenable = ($asyncbind.EagerThenableFactory = function (tick) {
        tick = tick || typeof process === "object" && process.nextTick || typeof setImmediate === "function" && setImmediate || function (f) {
          setTimeout(f, 0);
        };
  
        var soon = function () {
          var fq = [],
              fqStart = 0,
              bufferSize = 1024;
  
          function callQueue() {
            while (fq.length - fqStart) {
              try {
                fq[fqStart]();
              } catch (ex) {}
  
              fq[fqStart++] = undefined;
  
              if (fqStart === bufferSize) {
                fq.splice(0, bufferSize);
                fqStart = 0;
              }
            }
          }
  
          return function (fn) {
            fq.push(fn);
            if (fq.length - fqStart === 1) tick(callQueue);
          };
        }();
  
        function Zousan(func) {
          if (func) {
            var me = this;
            func(function (arg) {
              me.resolve(arg);
            }, function (arg) {
              me.reject(arg);
            });
          }
        }
  
        Zousan.prototype = {
          resolve: function resolve(value) {
            if (this.state !== undefined) return;
            if (value === this) return this.reject(new TypeError("Attempt to resolve promise with self"));
            var me = this;
  
            if (value && (typeof value === "function" || typeof value === "object")) {
              try {
                var first = 0;
                var then = value.then;
  
                if (typeof then === "function") {
                  then.call(value, function (ra) {
                    if (!first++) {
                      me.resolve(ra);
                    }
                  }, function (rr) {
                    if (!first++) {
                      me.reject(rr);
                    }
                  });
                  return;
                }
              } catch (e) {
                if (!first) this.reject(e);
                return;
              }
            }
  
            this.state = STATE_FULFILLED;
            this.v = value;
            if (me.c) soon(function () {
              for (var n = 0, l = me.c.length; n < l; n++) {
                STATE_FULFILLED(me.c[n], value);
              }
            });
          },
          reject: function reject(reason) {
            if (this.state !== undefined) return;
            this.state = STATE_REJECTED;
            this.v = reason;
            var clients = this.c;
            if (clients) soon(function () {
              for (var n = 0, l = clients.length; n < l; n++) {
                STATE_REJECTED(clients[n], reason);
              }
            });
          },
          then: function then(onF, onR) {
            var p = new Zousan();
            var client = {
              y: onF,
              n: onR,
              p: p
            };
  
            if (this.state === undefined) {
              if (this.c) this.c.push(client);else this.c = [client];
            } else {
              var s = this.state,
                  a = this.v;
              soon(function () {
                s(client, a);
              });
            }
  
            return p;
          }
        };
  
        function STATE_FULFILLED(c, arg) {
          if (typeof c.y === "function") {
            try {
              var yret = c.y.call(undefined, arg);
              c.p.resolve(yret);
            } catch (err) {
              c.p.reject(err);
            }
          } else c.p.resolve(arg);
        }
  
        function STATE_REJECTED(c, reason) {
          if (typeof c.n === "function") {
            try {
              var yret = c.n.call(undefined, reason);
              c.p.resolve(yret);
            } catch (err) {
              c.p.reject(err);
            }
          } else c.p.reject(reason);
        }
  
        Zousan.resolve = function (val) {
          if (val && val instanceof Zousan) return val;
          var z = new Zousan();
          z.resolve(val);
          return z;
        };
  
        Zousan.reject = function (err) {
          if (err && err instanceof Zousan) return err;
          var z = new Zousan();
          z.reject(err);
          return z;
        };
  
        Zousan.version = "2.3.3-nodent";
        return Zousan;
      })();
    }
  
    function boundThen() {
      return resolver.apply(self, arguments);
    }
  
    var resolver = this;
  
    switch (catcher) {
      case true:
        return new $asyncbind.Thenable(boundThen);
  
      case 0:
        return new $asyncbind.LazyThenable(boundThen);
  
      case undefined:
        boundThen.then = boundThen;
        return boundThen;
  
      default:
        return function () {
          try {
            return resolver.apply(self, arguments);
          } catch (ex) {
            return catcher(ex);
          }
        };
    }
  };
  
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
  
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; }
  
  // tslint:disable-next-line:no-var-requires
  global.Promise = require('bluebird');
  
  var couchdb = function couchdb(couchAuthDB) {
    var storeKey =
    /*#__PURE__*/
    function () {
      var _ref = _asyncToGenerator(function* (username, key, password, expires, roles) {
        var newKey = {
          _id: "org.couchdb.user:" + key,
          type: 'user',
          name: key,
          user_id: username,
          password: password,
          expires: expires,
          roles: ["user:" + username].concat(roles)
        };
        yield couchAuthDB.upsert(newKey._id, function (oldKey) {
          return (0, _lodash.default)({}, oldKey, newKey);
        });
        return _extends({}, newKey, {
          _id: key
        });
      });
  
      return function storeKey(_x, _x2, _x3, _x4, _x5) {
        return _ref.apply(this, arguments);
      };
    }();
  
    var removeKeys =
    /*#__PURE__*/
    function () {
      var _ref2 = _asyncToGenerator(function* (keys) {
        keys = _util.default.toArray(keys); // Transform the list to contain the CouchDB _user ids
  
        var keylist = keys.filter(function (k) {
          return k;
        }).map(function (key) {
          return "org.couchdb.user:" + key;
        });
  
        try {
          var keyDocs = yield couchAuthDB.allDocs({
            keys: keylist
          });
  
          if (keyDocs.rows && keyDocs.rows.length > 0) {
            var toDelete = keyDocs.rows.reduce(function (r, row) {
              return !row.value || row.value.deleted ? r : r.concat([{
                _id: row.id,
                _rev: row.value.rev,
                _deleted: true
              }]);
            }, []);
  
            if (toDelete.length > 0) {
              return yield couchAuthDB.bulkDocs(toDelete);
            }
          }
  
          return Promise.resolve(false);
        } catch (error) {
          console.error('error removing keys!', error);
          return Promise.resolve(false);
        }
      });
  
      return function removeKeys(_x6) {
        return _ref2.apply(this, arguments);
      };
    }();
  
    var initSecurity =
    /*#__PURE__*/
    function () {
      var _ref3 = _asyncToGenerator(function* (db, adminRoles, memberRoles) {
        try {
          var security = db.security();
          yield security.fetch();
          security.members.roles.add(memberRoles);
          security.admins.roles.add(adminRoles);
          return yield security.save();
        } catch (error) {
          console.error('error initializing security', error);
          return Promise.resolve(false);
        }
      });
  
      return function initSecurity(_x7, _x8, _x9) {
        return _ref3.apply(this, arguments);
      };
    }();
  
    var authorizeKeys =
    /*#__PURE__*/
    function () {
      var _ref4 = _asyncToGenerator(function* (user_id, db, keys) {
        try {
          var security = db.security();
          yield security.fetch();
          security.members.names.add(keys);
          return yield security.save();
        } catch (error) {
          console.error('error authorizing keys', error);
          return Promise.resolve(false);
        }
      });
  
      return function authorizeKeys(_x10, _x11, _x12) {
        return _ref4.apply(this, arguments);
      };
    }();
  
    var deauthorizeKeys =
    /*#__PURE__*/
    function () {
      var _ref5 = _asyncToGenerator(function* (db, keys) {
        keys = _util.default.toArray(keys);
  
        try {
          var security = db.security();
          yield security.fetch();
          security.members.names.remove(keys);
          return yield security.save();
        } catch (error) {
          console.error('error deauthorizing keys!', error);
          return Promise.resolve(false);
        }
      });
  
      return function deauthorizeKeys(_x13, _x14) {
        return _ref5.apply(this, arguments);
      };
    }();
  
    return {
      initSecurity: initSecurity,
      authorizeKeys: authorizeKeys,
      deauthorizeKeys: deauthorizeKeys,
      removeKeys: removeKeys,
      storeKey: storeKey
    };
  };
  
  var _default = couchdb;
  exports.default = _default;