mongo-col
Version:
mongoDB collection wrapper
185 lines (156 loc) • 5.06 kB
JavaScript
var mongodb = require("mongodb")
var Db = mongodb.Db
var Server = mongodb.Server
var process = require("process")
var extend = require("pd").extend
// Grab the database HOST, PORT, USER and PASSWORD from the environment
var HOST = process.env.MONGODB_HOST || "localhost"
var PORT = +process.env.MONGODB_PORT || 27017
var USER = process.env.MONGODB_USER
var PASSWORD = process.env.MONGODB_PASSWORD
var DB = process.env.MONGODB_DB || "DATABASE"
var cachedResults
var callbackQueue
var collectionCallbackQueue = {}
var Collection = {
constructor: function (collection, callback) {
collection(returnCollection.bind(this))
this.collection = collection
return this
function returnCollection(err, collection) {
this._collection = collection
if (callback) {
callback(this)
}
}
}
}
Object.keys(mongodb.Collection.prototype).forEach(addToCollection)
collection.mongo = mongo
collection.Collection = Collection
collection.ObjectID = mongodb.ObjectID
collection.close = function (cb) {
cachedResults[1].close(cb)
}
module.exports = collection
function mongo(collectionName, databaseName) {
return getCollection
function getCollection(callback) {
var db
openDatabase(databaseName || DB, openCollection)
function openCollection(err, database) {
if (err) {
return callback(err)
}
db = database
getCollection.db = db
db.collection(collectionName, { safe: true }, callCallback)
}
function callCallback(err, collection) {
if (err && err.message.indexOf(" does not exist") !== -1) {
createCollection(db, collectionName, callback)
} else {
callback.call(collection, err, collection)
}
}
}
}
function createCollection(db, name, callback) {
if (collectionCallbackQueue[name]) {
return collectionCallbackQueue[name].push(callback)
}
collectionCallbackQueue[name] = [callback]
db.createCollection(name, { safe: true }, function (err, col) {
var list = collectionCallbackQueue[name];
delete collectionCallbackQueue[name]
list.forEach(function (cb) {
cb.call(col, err, col)
})
})
}
function openDatabase(databaseName, callback) {
if (cachedResults) {
return callback.apply(cachedResults[1], cachedResults)
} else if (callbackQueue) {
return callbackQueue.push(callback)
}
var db
callbackQueue = [callback]
if (typeof databaseName === "object" && databaseName !== null) {
db = databaseName
} else {
db = new Db(databaseName, new Server(HOST, PORT, {
auto_reconnect: true,
poolSize: 4
}), { safe: true })
}
db.open(authenticateDatabase)
function authenticateDatabase(err, db) {
if (err) {
return invokeCallbacks(err)
}
if (USER || PASSWORD) {
db.authenticate(USER, PASSWORD, saveDatabase)
} else {
invokeCallbacks(err, db)
}
function saveDatabase(err, success) {
if (success) {
return invokeCallbacks(err, db)
}
return invokeCallbacks(new Error("auth failed"))
}
}
function invokeCallbacks(err, data) {
var callbackList = callbackQueue
cachedResults = arguments
callbackQueue = null
for (var i = 0, len = callbackList.length; i < len; i++) {
callbackList[i].apply(data, arguments)
}
}
}
function collection (collectionName, databaseName, callback) {
if (typeof databaseName === "function") {
callback = databaseName
databaseName = null
}
return extend({}, Collection).constructor(
mongo(collectionName, databaseName), callback)
}
function addToCollection(methodName) {
if (typeof mongodb.Collection.prototype[methodName] === "function" &&
methodName !== "constructor"
) {
Collection[methodName] = tunnel(methodName)
}
}
function tunnel(methodName) {
return proxy
function proxy() {
var args = arguments,
callback = args[args.length - 1]
if (this._collection) {
this[methodName] = makeCachedProxy(methodName)
return this[methodName].apply(this, args)
}
this.collection(invokeMethod)
function invokeMethod(err, collection) {
if (err) {
if (typeof callback === "function") {
callback(err)
}
console.log("Error: in mongo-col", err)
return
}
collection[methodName].apply(collection, args)
}
}
}
function makeCachedProxy(methodName) {
return proxy
function proxy() {
var collection = this._collection
return collection[methodName].apply(collection, arguments)
}
}