ac-node
Version:
A common module for building Atlassian Connect add-ons
132 lines (121 loc) • 3.93 kB
JavaScript
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;