You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

182 lines
4.6 KiB

var Collection = require('./collection')
var mongodb = require('mongodb')
var xtend = require('xtend')
var thunky = require('thunky')
var parse = require('parse-mongo-url')
var util = require('util')
var EventEmitter = require('events').EventEmitter
var noop = function () {}
var Database = function (connString, cols, options) {
var self = this
EventEmitter.call(this)
if (typeof connString === 'string') {
this._dbname = parse(connString).dbName
// Fix short cut connection URLs consisting only of a db name or db + host
if (connString.indexOf('/') < 0) {
connString = 'localhost/' + connString
}
if (connString.indexOf('mongodb://') < 0) {
connString = 'mongodb://' + connString
}
this._getConnection = thunky(function (cb) {
mongodb.connect(connString, options, function (err, db) {
if (err) {
self.emit('error', err) // It's safer to emit an error instead of rely on the cb to handle the error
return cb(err)
}
self.emit('connect')
cb(null, db)
})
})
} else if (typeof connString._getConnection === 'function') { // mongojs
this._dbname = connString._dbname
this._getConnection = connString._getConnection
} else { // try mongodb-native
this._dbname = parse(connString.options.url).dbName
this._getConnection = thunky(function (cb) {
cb(null, connString)
})
}
this.ObjectId = mongodb.ObjectId
cols = cols || []
cols.forEach(function (colName) {
self[colName] = self.collection(colName)
var parts = colName.split('.')
var last = parts.pop()
var parent = parts.reduce(function (parent, prefix) {
parent[prefix] = parent[prefix] || {}
return parent[prefix]
}, self)
parent[last] = self.collection(colName)
})
}
util.inherits(Database, EventEmitter)
Database.prototype.collection = function (colName) {
return new Collection({name: colName}, this._getConnection)
}
Database.prototype.close = function (force, cb) {
if (typeof force === 'function') { return this.close(false, force) }
var self = this
cb = cb || noop
this._getConnection(function (err, server) {
if (err) return cb(err)
server.close(force)
self.emit('close')
cb()
})
}
Database.prototype.runCommand = function (opts, cb) {
cb = cb || noop
if (typeof opts === 'string') {
var tmp = opts
opts = {}
opts[tmp] = 1
}
this._getConnection(function (err, connection) {
if (err) return cb(err)
connection.command(opts, function (err, result) {
if (err) return cb(err)
cb(null, result)
})
})
}
Database.prototype.listCollections = function (cb) {
this._getConnection(function (err, connection) {
if (err) { return cb(err) }
connection.listCollections().toArray(function (err, collections) {
if (err) { return cb(err) }
cb(null, collections)
})
})
}
Database.prototype.getCollectionNames = function (cb) {
this.listCollections(function (err, collections) {
if (err) { return cb(err) }
cb(null, collections.map(function (collection) { return collection.name }))
})
}
Database.prototype.createCollection = function (name, opts, cb) {
if (typeof opts === 'function') return this.createCollection(name, {}, opts)
var cmd = {create: name}
Object.keys(opts).forEach(function (opt) {
cmd[opt] = opts[opt]
})
this.runCommand(cmd, cb)
}
Database.prototype.stats = function (scale, cb) {
if (typeof scale === 'function') return this.stats(1, scale)
this.runCommand({dbStats: 1, scale: scale}, cb)
}
Database.prototype.dropDatabase = function (cb) {
this.runCommand('dropDatabase', cb)
}
Database.prototype.createUser = function (usr, cb) {
var cmd = xtend({createUser: usr.user}, usr)
delete cmd.user
this.runCommand(cmd, cb)
}
Database.prototype.addUser = Database.prototype.createUser
Database.prototype.dropUser = function (username, cb) {
this.runCommand({dropUser: username}, cb)
}
Database.prototype.removeUser = Database.prototype.dropUser
Database.prototype.eval = function (fn) {
var cb = arguments[arguments.length - 1]
this.runCommand({
eval: fn.toString(),
args: Array.prototype.slice.call(arguments, 1, arguments.length - 1)
}, function (err, res) {
if (err) return cb(err)
cb(null, res.retval)
})
}
Database.prototype.getLastErrorObj = function (cb) {
this.runCommand('getLastError', cb)
}
Database.prototype.getLastError = function (cb) {
this.runCommand('getLastError', function (err, res) {
if (err) return cb(err)
cb(null, res.err)
})
}
Database.prototype.toString = function () {
return this._dbname
}
module.exports = Database