UNPKG

ac-node

Version:

A common module for building Atlassian Connect add-ons

132 lines (121 loc) 3.93 kB
var rsvp = require('rsvp'); var Promise = rsvp.Promise; var mongo = require('mongodb'); var _ = require('lodash'); function MongoStore(mongoUrlOrDbPromise, scope, dbName) { if (!(this instanceof MongoStore)) { return new MongoStore(mongoUrlOrDbPromise, scope, dbName); } if (mongoUrlOrDbPromise) { if (typeof mongoUrlOrDbPromise === 'object') { this._db = mongoUrlOrDbPromise; } else { this._db = connect(mongoUrlOrDbPromise); } } else { this._db = connect('mongodb://127.0.0.1:27017/' + (dbName || 'ac')); } this._scope = scope = scope || 'ac'; this._collection = this._db.then(function (db) { return db.collection(scope); }); }; MongoStore.prototype.get = function (key) { return this._collection.then(function (collection) { return new Promise(function (resolve, reject) { collection.findOne({key: key}, function (err, result) { if (err) return reject(err); var value; if (result && (!result.expires || result.expires.getTime() > Date.now())) { value = result.value; } resolve(value); }); }); }); }; MongoStore.prototype.set = function (key, value, expiresIn) { var self = this; return self._collection.then(function (collection) { function doInsert(resolve, reject, expires) { var doc = {key: key, value: value}; var expiry = expires ? Date.now() + (expiresIn * 1000) : null; if (expiry) { doc.expires = new Date(expiry); } collection.update({key: key}, doc, {upsert: true}, function (err, result) { if (err) return reject(err); resolve(); }); } if (expiresIn > 0) { self._indexes = self._indexes || {}; if (self._indexes[key] > 0 && self._indexes[key] !== expiresIn) { throw new Error('Cannot assign a new ttl for previously indexed key ' + key); } return new Promise(function (resolve, reject) { collection.ensureIndex({expires: 1}, {expireAfterSeconds: 0}, function (err) { self._indexes[key] = expiresIn; if (err) return reject(err); doInsert(resolve, reject, true); }); }); } return new Promise(doInsert); }); }; MongoStore.prototype.del = function (key) { return this._collection.then(function (collection) { return new Promise(function (resolve, reject) { collection.remove({key: key}, function (err) { if (err) return reject(err); resolve(); }); }); }); }; MongoStore.prototype.all = function (limit, offset) { limit = limit >>> 0; offset = offset >>> 0; return this._collection.then(function (collection) { return new Promise(function (resolve, reject) { var cursor = collection.find(); if (limit > 0) cursor.limit(limit); if (offset > 0) cursor.skip(offset); cursor.toArray(function (err, results) { if (err) return reject(err); resolve(_.object(results.map(function (result) { return [result.key, result.value]; }))); }); }); }); }; MongoStore.prototype.narrow = function (subscope) { subscope = this._scope ? this._scope + ':' + subscope : subscope; return MongoStore(this._db, subscope); }; MongoStore.prototype.clear = function () { var self = this; return this._collection.then(function (collection) { return new Promise(function (resolve, reject) { collection.remove(function (err) { if (err) return reject(err); resolve(); }); }); }); }; MongoStore.create = function (config, scope, dbName) { var url = config.MONGO_ENV && process.env[config.MONGO_ENV]; return MongoStore(url, scope, dbName); }; function connect(mongoUrl) { return new Promise(function (resolve, reject) { mongo.MongoClient.connect(mongoUrl, function (err, db) { if (err) return reject(err); resolve(db); }); }); } module.exports = MongoStore;