Comparing version
var mongoskin = require('../lib/mongoskin/'); | ||
require('myconsole').replace(); | ||
exports.db = mongoskin.db('localhost/test'); | ||
exports.db = mongoskin.db('localhost/test'); | ||
mongoskin.db('localhost', { database: 'test' }); |
@@ -1,1 +0,1 @@ | ||
module.exports = require('./lib/mongoskin'); | ||
module.exports = process.env.MONGOSKIN_COV ? require('./lib-cov/mongoskin') : require('./lib/mongoskin'); |
@@ -1,35 +0,67 @@ | ||
var Admin = require('mongodb').Admin | ||
, utils = require('./utils'); | ||
/*! | ||
* mongoskin - admin.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
var SkinAdmin = exports.SkinAdmin = function(skinDb) { | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var Admin = require('mongodb').Admin; | ||
var utils = require('./utils'); | ||
var constant = require('./constant'); | ||
/** | ||
* SkinAdmin | ||
* | ||
* @param {SkinDb} skinDb | ||
* @constructor | ||
* @api public | ||
*/ | ||
var SkinAdmin = exports.SkinAdmin = function (skinDb) { | ||
utils.SkinObject.call(this); | ||
this.skinDb = skinDb; | ||
} | ||
this.admin = null; | ||
}; | ||
SkinAdmin.prototype.open = function(callback) { | ||
if(this.admin) return callback(null, this.admin); | ||
this.skinDb.open(function(err, db){ | ||
if(err) return callback(err); | ||
utils.inherits(SkinAdmin, utils.SkinObject); | ||
/** | ||
* Retrieve mongodb.Admin instance. | ||
* | ||
* @param {Function(err, admin)} callback | ||
* @return {SkinAdmin} this | ||
* @api public | ||
*/ | ||
SkinAdmin.prototype.open = function (callback) { | ||
if (this.state === constant.STATE_OPEN) { | ||
callback(null, this.admin); | ||
return this; | ||
} | ||
this.emitter.once('open', callback); | ||
if (this.state === constant.STATE_OPENNING) { | ||
return this; | ||
} | ||
this.state = constant.STATE_OPENNING; | ||
this.skinDb.open(function (err, db) { | ||
if (err) { | ||
this.admin = null; | ||
this.state = constant.STATE_CLOSE; | ||
} else { | ||
this.admin = new Admin(db); | ||
callback(null, this.admin); | ||
}) | ||
} | ||
var bindSkin = function(name, method) { | ||
SkinAdmin.prototype[name] = function() { | ||
var args = arguments.length > 0 ? Array.prototype.slice.call(arguments, 0) : []; | ||
return this.open(function(err, admin) { | ||
if (err) { | ||
utils.error(err, args, 'SkinAdmin.' + name); | ||
} else { | ||
method.apply(admin, args); | ||
} | ||
}); | ||
}; | ||
this.state = constant.STATE_OPEN; | ||
} | ||
this.emitter.emit('open', err, this.admin); | ||
}.bind(this)); | ||
return this; | ||
}; | ||
for (var name in Admin.prototype) { | ||
var method = Admin.prototype[name]; | ||
bindSkin(name, method); | ||
} | ||
exports.SkinAdmin = SkinAdmin; | ||
for (var key in Admin.prototype) { | ||
var method = Admin.prototype[key]; | ||
utils.bindSkin('SkinAdmin', SkinAdmin, 'admin', key, method); | ||
} |
@@ -0,2 +1,16 @@ | ||
/*! | ||
* mongoskin - collection.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
/** | ||
bind these methods from Collection.prototype to Provider | ||
@@ -27,10 +41,11 @@ | ||
*/ | ||
var __slice = Array.prototype.slice, | ||
events = require('events'), | ||
Collection = require('mongodb').Collection, | ||
SkinCursor = require('./cursor').SkinCursor, | ||
utils = require('./utils'), | ||
STATE_CLOSE = 0, | ||
STATE_OPENNING = 1, | ||
STATE_OPEN = 2; | ||
var __slice = Array.prototype.slice; | ||
var events = require('events'); | ||
var Collection = require('mongodb').Collection; | ||
var SkinCursor = require('./cursor').SkinCursor; | ||
var utils = require('./utils'); | ||
var constant = require('./constant'); | ||
var STATE_CLOSE = constant.STATE_CLOSE; | ||
var STATE_OPENNING = constant.STATE_OPENNING; | ||
var STATE_OPEN = constant.STATE_OPEN; | ||
@@ -41,45 +56,32 @@ /** | ||
* | ||
* @param skinDb | ||
* @param collectionName | ||
* | ||
* @param {SkinDb} skinDb | ||
* @param {String} collectionName | ||
* @constructor | ||
* @api public | ||
*/ | ||
var SkinCollection = exports.SkinCollection = function(skinDb, collectionName) { | ||
var SkinCollection = exports.SkinCollection = function (skinDb, collectionName) { | ||
utils.SkinObject.call(this); | ||
this.skinDb = skinDb; | ||
this.ObjectID = this.skinDb.ObjectID; | ||
this.collectionName = collectionName; | ||
this.collection; | ||
this.state = STATE_CLOSE; | ||
this.internalHint; | ||
var that = this; | ||
this.__defineGetter__('hint', function() { return this.internalHint; }); | ||
this.__defineSetter__('hint', function(value) { | ||
this.internalHint = value; | ||
this.open(function(err, collection) { | ||
collection.hint = value; | ||
that.internalHint = collection.hint; | ||
}); | ||
this.collection = null; | ||
this.internalHint = null; | ||
this.__defineGetter__('hint', function () { | ||
return this.internalHint; | ||
}); | ||
this.emitter = new events.EventEmitter(); | ||
this.__defineSetter__('hint', function (value) { | ||
this.internalHint = value; | ||
this.open(function (err, collection) { | ||
collection.hint = value; | ||
this.internalHint = collection.hint; | ||
}.bind(this)); | ||
}); | ||
}; | ||
/** | ||
* bind method of mongodb.Collection to mongoskin.SkinCollection | ||
*/ | ||
var bindSkin = function(name, method) { | ||
SkinCollection.prototype[name] = function() { | ||
var args = arguments.length > 0 ? __slice.call(arguments, 0) : []; | ||
this.open(function(err, collection) { | ||
if (err) { | ||
utils.error(err, args, 'SkinCollection.' + name); | ||
} else { | ||
method.apply(collection, args); | ||
} | ||
}); | ||
}; | ||
}; | ||
utils.inherits(SkinCollection, utils.SkinObject); | ||
for (var name in Collection.prototype) { | ||
var method = Collection.prototype[name]; | ||
bindSkin(name, method); | ||
for (var _name in Collection.prototype) { | ||
var method = Collection.prototype[_name]; | ||
utils.bindSkin('SkinCollection', SkinCollection, 'collection', _name, method); | ||
} | ||
@@ -93,43 +95,67 @@ | ||
/** | ||
* retrieve mongodb.Collection | ||
* Retrieve mongodb.Collection | ||
* | ||
* @param {Function(err, collection)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.open = function(fn) { | ||
SkinCollection.prototype.open = function (callback) { | ||
switch (this.state) { | ||
case STATE_OPEN: | ||
return fn(null, this.collection); | ||
callback(null, this.collection); | ||
break; | ||
case STATE_OPENNING: | ||
return this.emitter.once('open', fn); | ||
case STATE_CLOSE: | ||
this.emitter.once('open', callback); | ||
break; | ||
// case STATE_CLOSE: | ||
default: | ||
var that = this; | ||
this.emitter.once('open', fn); | ||
this.emitter.once('open', callback); | ||
this.state = STATE_OPENNING; | ||
this.skinDb.open(function(err, db) { | ||
this.skinDb.open(function (err, db) { | ||
if (err) { | ||
this.state = STATE_CLOSE; | ||
return this.emitter.emit('open', err, null); | ||
} | ||
db.collection(this.collectionName, function (err, collection) { | ||
if (err) { | ||
that.state = STATE_CLOSE; | ||
return that.emitter.emit('open', err, null); | ||
this.state = STATE_CLOSE; | ||
} else { | ||
this.state = STATE_OPEN; | ||
this.collection = collection; | ||
if (this.hint) { | ||
this.collection.hint = this.hit; | ||
} | ||
} | ||
that.skinDb.db.collection(that.collectionName, function(err, collection) { | ||
if (collection) { | ||
that.state = STATE_OPEN; | ||
that.collection = collection; | ||
if (that.hint) { | ||
that.collection.hint = that.hit; | ||
} | ||
}else { | ||
that.state = STATE_CLOSE; | ||
} | ||
that.emitter.emit('open', err, collection); | ||
}); | ||
}); | ||
this.emitter.emit('open', err, collection); | ||
}.bind(this)); | ||
}.bind(this)); | ||
break; | ||
} | ||
return this; | ||
}; | ||
SkinCollection.prototype.close = function(){ | ||
/** | ||
* Close current collection. | ||
* | ||
* @param {Function(err)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.close = function (callback) { | ||
this.collection = null; | ||
this.state = STATE_CLOSE; | ||
return this; | ||
}; | ||
SkinCollection.prototype.drop = function(fn) { | ||
this.skinDb.dropCollection(this.collectionName, fn); | ||
/** | ||
* Drop current collection. | ||
* | ||
* @param {Function(err)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.drop = function (callback) { | ||
this.skinDb.dropCollection(this.collectionName, callback); | ||
this.close(); | ||
return this; | ||
}; | ||
@@ -140,46 +166,64 @@ | ||
* | ||
* findItems(args, function(err, items){}); | ||
* findItems(args, function (err, items) {}); | ||
* | ||
* same as | ||
* | ||
* find(args, function(err, cursor){cursor.toArray(err, items){}}); | ||
* find(args).toArray(function (err, items) {}); | ||
* | ||
* or using `mongodb.collection.find()` | ||
* | ||
* find(args, function (err, cursor) { | ||
* cursor.toArray(function (err, items) { | ||
* }); | ||
* }); | ||
* | ||
* @param {Object} [query] | ||
* @param {Object} [options] | ||
* @param {Function(err, docs)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.findItems = function() { | ||
var args = __slice.call(arguments), | ||
fn = args[args.length - 1]; | ||
args[args.length - 1] = function(err, cursor) { | ||
SkinCollection.prototype.findItems = function (query, options, callback) { | ||
var args = __slice.call(arguments); | ||
var fn = args[args.length - 1]; | ||
args[args.length - 1] = function (err, cursor) { | ||
if (err) { | ||
fn(err); | ||
} else { | ||
cursor.toArray(fn); | ||
return fn(err); | ||
} | ||
} | ||
this._find.apply(this, args); | ||
cursor.toArray(fn); | ||
}; | ||
this.find.apply(this, args); | ||
return this; | ||
}; | ||
/** | ||
* find and cursor.each | ||
* find and cursor.each(fn). | ||
* | ||
* @param {Object} [query] | ||
* @param {Object} [options] | ||
* @param {Function(err, item)} eachCallback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.findEach = function() { | ||
var args = __slice.call(arguments), | ||
fn = args[args.length - 1]; | ||
args[args.length - 1] = function(err, cursor) { | ||
SkinCollection.prototype.findEach = function (query, options, eachCallback) { | ||
var args = __slice.call(arguments); | ||
var fn = args[args.length - 1]; | ||
args[args.length - 1] = function (err, cursor) { | ||
if (err) { | ||
fn(err); | ||
} else { | ||
cursor.each(fn); | ||
return fn(err); | ||
} | ||
} | ||
this._find.apply(this, args); | ||
cursor.each(fn); | ||
}; | ||
this.find.apply(this, args); | ||
return this; | ||
}; | ||
/** | ||
* @deprecated use SkinDb.id instead | ||
* @deprecated use `SkinDb.toId` instead | ||
* | ||
* @param {String} hex | ||
* @return {ObjectID|String} | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.id = function(hex) { | ||
SkinCollection.prototype.id = function (hex) { | ||
return this.skinDb.toId(hex); | ||
@@ -189,44 +233,70 @@ }; | ||
/** | ||
* use hex id as first argument, support ObjectID and String id | ||
* Operate by object.`_id` | ||
* | ||
* @param {String/ObjectID} id | ||
* @param {Function} callback | ||
* @return {Object} cursor | ||
* @param {String} methodName | ||
* @param {String|ObjectID|Number} id | ||
* @param {Arguments|Array} args | ||
* @return {SkinCollection} this | ||
* @api private | ||
*/ | ||
SkinCollection.prototype._operateById = function (methodName, id, args) { | ||
args = __slice.call(args); | ||
args[0] = {_id: this.skinDb.toId(id)}; | ||
this[methodName].apply(this, args); | ||
return this; | ||
}; | ||
/** | ||
* Find one object by _id. | ||
* | ||
* @param {String|ObjectID|Number} id, doc primary key `_id` | ||
* @param {Function(err, doc)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.findById = function() { | ||
var args = __slice.call(arguments); | ||
args[0] = {_id: this.skinDb.toId(args[0])}; | ||
this.findOne.apply(this, args); | ||
SkinCollection.prototype.findById = function (id, callback) { | ||
return this._operateById('findOne', id, arguments); | ||
}; | ||
/** | ||
* use hex id as first argument | ||
* Update doc by _id. | ||
* @param {String|ObjectID|Number} id, doc primary key `_id` | ||
* @param {Object} doc | ||
* @param {Function(err)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.updateById = function() { | ||
var args = __slice.call(arguments); | ||
args[0] = {_id: this.skinDb.toId(args[0])}; | ||
this.update.apply(this, args); | ||
SkinCollection.prototype.updateById = function (id, doc, callback) { | ||
return this._operateById('update', id, arguments); | ||
}; | ||
/** | ||
* use hex id as first argument | ||
* Remove doc by _id. | ||
* @param {String|ObjectID|Number} id, doc primary key `_id` | ||
* @param {Function(err)} callback | ||
* @return {SkinCollection} this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.removeById = function() { | ||
var args = __slice.call(arguments); | ||
args[0] = {_id: this.skinDb.toId(args[0])}; | ||
this.remove.apply(this, args); | ||
SkinCollection.prototype.removeById = function (id, callback) { | ||
return this._operateById('remove', id, arguments); | ||
}; | ||
/** | ||
* if last argument is not a function, then returns a SkinCursor | ||
* Creates a cursor for a query that can be used to iterate over results from MongoDB. | ||
* | ||
* @param {Object} query | ||
* @param {Object} options | ||
* @param {Function(err, docs)} callback | ||
* @return {SkinCursor|SkinCollection} if last argument is not a function, then returns a SkinCursor, | ||
* otherise return this | ||
* @api public | ||
*/ | ||
SkinCollection.prototype.find = function() { | ||
var args = arguments.length > 0 ? __slice.call(arguments, 0) : []; | ||
if (args.length > 0 && typeof(args[args.length - 1]) === 'function') { | ||
SkinCollection.prototype.find = function (query, options, callback) { | ||
var args = __slice.call(arguments); | ||
if (args.length > 0 && typeof args[args.length - 1] === 'function') { | ||
this._find.apply(this, args); | ||
}else { | ||
return this; | ||
} else { | ||
return new SkinCursor(null, this, args); | ||
} | ||
}; | ||
}; |
@@ -1,77 +0,87 @@ | ||
var __slice = Array.prototype.slice, | ||
events = require('events'), | ||
Cursor = require('mongodb').Cursor, | ||
utils = require('./utils'), | ||
STATE_CLOSE = 0, | ||
STATE_OPENNING = 1, | ||
STATE_OPEN = 2; | ||
/*! | ||
* mongoskin - cursor.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* MIT Licensed | ||
*/ | ||
var SkinCursor = exports.SkinCursor = function(cursor, skinCollection, args ) { | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var EventEmitter = require('events').EventEmitter; | ||
var Cursor = require('mongodb').Cursor; | ||
var utils = require('./utils'); | ||
var constant = require('./constant'); | ||
var STATE_CLOSE = constant.STATE_CLOSE; | ||
var STATE_OPENNING = constant.STATE_OPENNING; | ||
var STATE_OPEN = constant.STATE_OPEN; | ||
var SkinCursor = exports.SkinCursor = function (cursor, skinCollection, args) { | ||
utils.SkinObject.call(this); | ||
this.cursor = cursor; | ||
this.skinCollection = skinCollection; | ||
this.args = args; | ||
this.emitter = new events.EventEmitter(); | ||
if (!cursor) { | ||
this.state = STATE_CLOSE; | ||
}else { | ||
this.args = args || []; | ||
this.emitter = new EventEmitter(); | ||
if (cursor) { | ||
this.state = STATE_OPEN; | ||
} | ||
} | ||
}; | ||
SkinCursor.prototype.open = function(fn) { | ||
utils.inherits(SkinCursor, utils.SkinObject); | ||
/** | ||
* Retrieve mongodb.Cursor instance. | ||
* | ||
* @param {Function(err, cursor)} callback | ||
* @return {SkinCursor} this | ||
* @api public | ||
*/ | ||
SkinCursor.prototype.open = function (callback) { | ||
switch (this.state) { | ||
case STATE_OPEN: | ||
return fn(null, this.cursor); | ||
callback(null, this.cursor); | ||
break; | ||
case STATE_OPENNING: | ||
return this.emitter.once('open', fn); | ||
case STATE_CLOSE: | ||
this.emitter.once('open', callback); | ||
break; | ||
// case STATE_CLOSE: | ||
default: | ||
var that = this; | ||
this.emitter.once('open', fn); | ||
this.emitter.once('open', callback); | ||
this.state = STATE_OPENNING; | ||
this.skinCollection.open(function(err, collection) { | ||
this.skinCollection.open(function (err, collection) { | ||
if (err) { | ||
that.state = STATE_CLOSE; | ||
that.emitter.emit('open', err); | ||
return | ||
this.state = STATE_CLOSE; | ||
this.emitter.emit('open', err); | ||
return; | ||
} | ||
// copy args | ||
var args = that.args.slice(); | ||
args.push(function(err, cursor) { | ||
var args = this.args.slice(); | ||
args.push(function (err, cursor) { | ||
if (cursor) { | ||
that.state = STATE_OPEN; | ||
that.cursor = cursor; | ||
this.state = STATE_OPEN; | ||
this.cursor = cursor; | ||
} | ||
that.emitter.emit('open', err, cursor); | ||
}); | ||
this.emitter.emit('open', err, cursor); | ||
}.bind(this)); | ||
collection.find.apply(collection, args); | ||
}); | ||
}.bind(this)); | ||
break; | ||
} | ||
return this; | ||
}; | ||
var bindSkin = function(name, method) { | ||
SkinCursor.prototype[name] = function() { | ||
var args = arguments.length > 0 ? __slice.call(arguments, 0) : []; | ||
this.open(function(err, cursor) { | ||
if (err) { | ||
utils.error(err, args, 'SkinCursor.' + name); | ||
} else { | ||
method.apply(cursor, args); | ||
} | ||
}); | ||
return this; | ||
}; | ||
}; | ||
[ | ||
// callbacks | ||
'toArray','each','count','nextObject','getMore', 'explain', | ||
'toArray', 'each', 'count', 'nextObject', 'getMore', 'explain', | ||
// self return | ||
'sort','limit','skip','batchSize', | ||
'sort', 'limit', 'skip', 'batchSize', | ||
// unsupported | ||
//'rewind', 'close' ,... | ||
].forEach(function(name) { | ||
var method = Cursor.prototype[name]; | ||
bindSkin(name, method); | ||
].forEach(function (name) { | ||
var method = Cursor.prototype[name]; | ||
utils.bindSkin('SkinCursor', SkinCursor, 'cursor', name, method); | ||
}); |
@@ -1,27 +0,44 @@ | ||
var __slice = Array.prototype.slice, | ||
mongodb = require('mongodb'), | ||
events = require('events'), | ||
utils = require('./utils'), | ||
SkinAdmin = require('./admin').SkinAdmin, | ||
SkinCollection = require('./collection').SkinCollection, | ||
SkinGridStore = require('./gridfs').SkinGridStore, | ||
Db = mongodb.Db, | ||
/*! | ||
* mongoskin - db.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
STATE_CLOSE = 0, | ||
STATE_OPENNING = 1, | ||
STATE_OPEN = 2; | ||
"use strict"; | ||
var _extend = function(destination, source) { | ||
for (var property in source) { | ||
destination[property] = source[property]; | ||
} | ||
return destination; | ||
}; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var SkinDb = exports.SkinDb = function(db, username, password) { | ||
var __slice = Array.prototype.slice; | ||
var mongodb = require('mongodb'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var utils = require('./utils'); | ||
var SkinAdmin = require('./admin').SkinAdmin; | ||
var SkinCollection = require('./collection').SkinCollection; | ||
var SkinGridStore = require('./gridfs').SkinGridStore; | ||
var Db = mongodb.Db; | ||
var constant = require('./constant'); | ||
var STATE_CLOSE = constant.STATE_CLOSE; | ||
var STATE_OPENNING = constant.STATE_OPENNING; | ||
var STATE_OPEN = constant.STATE_OPEN; | ||
/** | ||
* SkinDb | ||
* | ||
* @param {Db} db, mongodb.Db instance | ||
* @param {String} [username] | ||
* @param {String} [password] | ||
* @constructor | ||
* @api public | ||
*/ | ||
var SkinDb = exports.SkinDb = function (db, username, password) { | ||
utils.SkinObject.call(this); | ||
this.emitter.setMaxListeners(100); | ||
this.db = db; | ||
this.username = username; | ||
this.password = password; | ||
this.state = STATE_CLOSE; | ||
this.emitter = new events.EventEmitter(); | ||
this.admin = new SkinAdmin(this); | ||
@@ -33,6 +50,17 @@ this._collections = {}; | ||
SkinDb.prototype.toObjectID = SkinDb.prototype.toId = function(hex) { | ||
if(hex instanceof this.ObjectID) { | ||
utils.inherits(SkinDb, utils.SkinObject); | ||
/** | ||
* Convert to ObjectID. | ||
* | ||
* @param {String} hex | ||
* @return {ObjectID} | ||
*/ | ||
SkinDb.prototype.toObjectID = SkinDb.prototype.toId = function (hex) { | ||
if (hex instanceof this.ObjectID) { | ||
return hex; | ||
} | ||
if (!hex || hex.length !== 24) { | ||
return hex; | ||
} | ||
return this.ObjectID.createFromHexString(hex); | ||
@@ -43,69 +71,77 @@ }; | ||
/** | ||
* retrieve native_db | ||
* Open the database connection. | ||
* | ||
* @param fn function(err, native_db) | ||
* | ||
* @param {Function(err, nativeDb)} [callback] | ||
* @return {SkinDb} this | ||
* @api public | ||
*/ | ||
SkinDb.prototype.open = function(fn) { | ||
SkinDb.prototype.open = function (callback) { | ||
switch (this.state) { | ||
case STATE_OPEN: | ||
return fn(null, this.db); | ||
case STATE_OPENNING: | ||
// if call 'open' method multi times before opened | ||
return this.emitter.once('open', fn); | ||
case STATE_CLOSE: | ||
default: | ||
var that = this; | ||
var onDbOpen = function(err, db) { | ||
if (!err && db) { | ||
that.state = STATE_OPEN; | ||
that.db = db; | ||
}else { | ||
db = null; | ||
that.state = STATE_CLOSE; | ||
} | ||
that.emitter.emit('open', err, db); | ||
}; | ||
this.emitter.once('open', fn); | ||
this.state = STATE_OPENNING; | ||
this.db.open(function(err, db) { | ||
if (db && that.username) { | ||
//do authenticate | ||
db.authenticate(that.username, that.password, function(err) { | ||
case STATE_OPEN: | ||
callback && callback(null, this.db); | ||
break; | ||
case STATE_OPENNING: | ||
// if call 'open' method multi times before opened | ||
callback && this.emitter.once('open', callback); | ||
break; | ||
// case STATE_CLOSE: | ||
default: | ||
var onDbOpen = function (err, db) { | ||
if (!err && db) { | ||
this.db = db; | ||
this.state = STATE_OPEN; | ||
} else { | ||
this.db = null; | ||
this.state = STATE_CLOSE; | ||
} | ||
this.emitter.emit('open', err, this.db); | ||
}.bind(this); | ||
callback && this.emitter.once('open', callback); | ||
this.state = STATE_OPENNING; | ||
this.db.open(function (err, db) { | ||
if (db && this.username) { | ||
// do authenticate | ||
db.authenticate(this.username, this.password, function (err) { | ||
onDbOpen(err, db); | ||
}); | ||
} else { | ||
onDbOpen(err, db); | ||
}); | ||
} else { | ||
onDbOpen(err, db); | ||
} | ||
}); | ||
} | ||
}.bind(this)); | ||
break; | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Close skinDb | ||
* Close the database connection. | ||
* | ||
* @param {Function(err)} [callback] | ||
* @return {SkinDb} this | ||
* @api public | ||
*/ | ||
SkinDb.prototype.close = function(callback) { | ||
SkinDb.prototype.close = function (callback) { | ||
if (this.state === STATE_CLOSE) { | ||
return callback && callback(); | ||
}else if (this.state === STATE_OPEN) { | ||
callback && callback(); | ||
} else if (this.state === STATE_OPEN) { | ||
this.state = STATE_CLOSE; | ||
this.db.close(callback); | ||
}else if (this.state === STATE_OPENNING) { | ||
} else if (this.state === STATE_OPENNING) { | ||
var that = this; | ||
this.emitter.once('open', function(err, db) { | ||
that.state = STATE_CLOSE; | ||
db.close(callback); | ||
}); | ||
this.emitter.once('open', function (err, db) { | ||
that.state = STATE_CLOSE; | ||
db ? db.close(callback) : callback && callback(err); | ||
}); | ||
} | ||
return this; | ||
}; | ||
/** | ||
* create or retrieval skin collection | ||
* Create or retrieval skin collection | ||
* | ||
* @param {String} name, the collection name. | ||
* @return {SkinCollection} | ||
* @api public | ||
*/ | ||
SkinDb.prototype.collection = function(name) { | ||
SkinDb.prototype.collection = function (name) { | ||
var collection = this._collections[name]; | ||
@@ -120,6 +156,9 @@ if (!collection) { | ||
* gridfs | ||
* | ||
* @return {SkinGridStore} | ||
* @api public | ||
*/ | ||
SkinDb.prototype.gridfs = function() { | ||
SkinDb.prototype.gridfs = function () { | ||
return this.skinGridStore || (this.skinGridStore = new SkinGridStore(this)); | ||
} | ||
}; | ||
@@ -132,9 +171,14 @@ /** | ||
* 3. collectionName, SkinCollection | ||
* | ||
* @param {String} collectionName | ||
* @param {Object|SkinCollection} [options] | ||
* @return {SkinCollection} | ||
* @api public | ||
*/ | ||
SkinDb.prototype.bind = function() { | ||
var args = __slice.call(arguments), | ||
name = args[0]; | ||
SkinDb.prototype.bind = function (collectionName, options) { | ||
var args = __slice.call(arguments); | ||
var name = args[0]; | ||
if (typeof name !== 'string' || name.length === 0) { | ||
throw new Error('Must provide name parameter for bind.'); | ||
if (typeof name !== 'string' || !name.trim()) { | ||
throw new Error('Must provide collection name to bind.'); | ||
} | ||
@@ -153,12 +197,12 @@ if (args.length === 1) { | ||
var names = name.split('.'); | ||
if(names.length > 1){ | ||
if (names.length > 1){ | ||
var prev = this, next; | ||
for(var i =0; i<names.length - 1; i++){ | ||
for (var i = 0; i < names.length - 1; i++) { | ||
next = prev[names[i]]; | ||
if(!next){ | ||
if (!next) { | ||
next = {}; | ||
Object.defineProperty(prev, names[i], { | ||
value : next | ||
, writable : false | ||
, enumerable : true | ||
value: next, | ||
writable: false, | ||
enumerable : true | ||
}); | ||
@@ -169,5 +213,5 @@ } | ||
Object.defineProperty(prev, names[names.length - 1], { | ||
value : args[1] | ||
, writable : false | ||
, enumerable : true | ||
value: args[1], | ||
writable: false, | ||
enumerable : true | ||
}); | ||
@@ -178,10 +222,9 @@ } | ||
for (var i = 1, len = args.length; i < len; i++) { | ||
if (typeof args[i] != 'object') | ||
throw new Error('the arg' + i + ' should be object, but is ' + args[i]); | ||
} | ||
var coll = this.collection(name); | ||
for (var i = 0, len = args.length; i < len; i++) { | ||
_extend(coll, args[i]); | ||
for (var index = 1, len = args.length; index < len; index++) { | ||
var extend = args[index]; | ||
if (typeof extend !== 'object') { | ||
throw new Error('the args[' + index + '] should be object, but is `' + extend + '`'); | ||
} | ||
utils.extend(coll, extend); | ||
} | ||
@@ -191,23 +234,12 @@ return this.bind(name, coll); | ||
var bindSkin = function(name, method) { | ||
return SkinDb.prototype[name] = function() { | ||
var args = arguments.length > 0 ? __slice.call(arguments, 0) : []; | ||
return this.open(function(err, db) { | ||
if (err) { | ||
utils.error(err, args, 'SkinDb.' + name); | ||
} else { | ||
return method.apply(db, args); | ||
} | ||
}); | ||
}; | ||
}; | ||
//bind method of mongodb.Db to SkinDb | ||
for (var name in Db.prototype) { | ||
if(!name || name[0] == '_' || name == 'state') continue; | ||
var method = Db.prototype[name]; | ||
if (name !== 'bind' && name !== 'open' && name !== 'collection' && name !== 'admin') { | ||
bindSkin(name, method); | ||
var IGNORE_NAMES = [ | ||
'bind', 'open', 'close', 'collection', 'admin', 'state' | ||
]; | ||
// bind method of mongodb.Db to SkinDb | ||
for (var key in Db.prototype) { | ||
if (!key || key[0] === '_' || IGNORE_NAMES.indexOf(key) >= 0) { | ||
continue; | ||
} | ||
var method = Db.prototype[key]; | ||
utils.bindSkin('SkinDb', SkinDb, 'db', key, method); | ||
} | ||
@@ -0,2 +1,16 @@ | ||
/*! | ||
* mongoskin - gridfs.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var GridStore = require('mongodb').GridStore; | ||
var utils = require('./utils'); | ||
@@ -6,6 +20,9 @@ /** | ||
*/ | ||
var SkinGridStore = exports.SkinGridStore = function(skinDb) { | ||
var SkinGridStore = exports.SkinGridStore = function (skinDb) { | ||
utils.SkinObject.call(this); | ||
this.skinDb = skinDb; | ||
} | ||
}; | ||
utils.inherits(SkinGridStore, utils.SkinObject); | ||
/** | ||
@@ -19,9 +36,20 @@ * @param id | ||
*/ | ||
SkinGridStore.prototype.open = function(id, filename, mode, options, callback){ | ||
SkinGridStore.prototype.open = function (id, filename, mode, options, callback) { | ||
var args = Array.prototype.slice.call(arguments); | ||
var callback = args.pop(); | ||
this.skinDb.open(function(err, db) { | ||
new GridStore(db, args[0], args[1], args[2], args[3]).open(callback); | ||
callback = args.pop(); | ||
this.skinDb.open(function (err, db) { | ||
var gs = new GridStore(db, args[0], args[1], args[2], args[3]); | ||
var props = { | ||
length: gs.length, | ||
contentType: gs.contentType, | ||
uploadDate: gs.uploadDate, | ||
metadata: gs.metadata, | ||
chunkSize: gs.chunkSize | ||
}; | ||
gs.open(function (error, reply) { | ||
callback(error, reply, props); | ||
}); | ||
}); | ||
} | ||
}; | ||
@@ -31,14 +59,12 @@ /** | ||
*/ | ||
SkinGridStore.prototype.unlink = SkinGridStore.prototype.remove = function(filename, callback){ | ||
this.skinDb.open(function(err, db) { | ||
GridStore.unlink(db, filename, callback); | ||
SkinGridStore.prototype.unlink = SkinGridStore.prototype.remove = function (filename, callback) { | ||
this.skinDb.open(function (err, db) { | ||
GridStore.unlink(db, filename, callback); | ||
}); | ||
} | ||
}; | ||
SkinGridStore.prototype.exist = function(filename, rootCollection, callback){ | ||
this.skinDb.open(function(err, db) { | ||
GridStore.exist(db, filename, rootCollection, callback); | ||
SkinGridStore.prototype.exist = function (filename, rootCollection, callback) { | ||
this.skinDb.open(function (err, db) { | ||
GridStore.exist(db, filename, rootCollection, callback); | ||
}); | ||
} | ||
exports.SkinGridStore = SkinGridStore; | ||
}; |
@@ -1,14 +0,28 @@ | ||
var url = require('url'), | ||
Router = require('./router').Router, | ||
mongo = require('mongodb'), | ||
SkinServer = require('./server').SkinServer, | ||
SkinDb =require('./db').SkinDb, | ||
Db = mongo.Db, | ||
Server = mongo.Server, | ||
ReplSetServers = mongo.ReplSetServers, | ||
BSONNative = mongo.BSONNative, | ||
DEFAULT_PORT = 27017; | ||
/*! | ||
* mongoskin - index.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var url = require('url'); | ||
var Router = require('./router').Router; | ||
var mongo = require('mongodb'); | ||
var SkinServer = require('./server').SkinServer; | ||
var SkinDb =require('./db').SkinDb; | ||
var Db = mongo.Db; | ||
var Server = mongo.Server; | ||
var ReplSetServers = mongo.ReplSetServers; | ||
var BSONNative = mongo.BSONNative; | ||
var constant = require('./constant'); | ||
var DEFAULT_PORT = constant.DEFAULT_PORT; | ||
function toBool(value) { | ||
return value !== undefined && value != 'false' && value != 'no' && value != 'off'; | ||
return value !== undefined && value !== 'false' && value !== 'no' && value !== 'off'; | ||
} | ||
@@ -21,21 +35,32 @@ | ||
* | ||
* @param {String} serverUrl | ||
* @return {Object} config | ||
* - {String} host | ||
* - {Number} port, default is `DEFAULT_PORT`. | ||
* - {String} [database], no database by default. | ||
* - {Object} options | ||
* - {Bool} auto_reconnect, default is `false`. | ||
* - {Number} poolSize, default is `1`. | ||
* - {String} [username], no username by default. | ||
* - {String} [password], no password by default. | ||
* @api private | ||
*/ | ||
var parseUrl = function(serverUrl) { | ||
var serverUrl = /\w+:\/\//.test(serverUrl) ? serverUrl : 'db://' + serverUrl, | ||
uri = url.parse(serverUrl, true), | ||
config = {}, | ||
serverOptions = uri.query, | ||
reconnect = serverOptions['auto_reconnect']; | ||
var parseUrl = function (serverUrl) { | ||
serverUrl = /\w+:\/\//.test(serverUrl) ? serverUrl : 'db://' + serverUrl; | ||
var uri = url.parse(serverUrl, true); | ||
var config = {}; | ||
var serverOptions = uri.query; | ||
var reconnect = serverOptions.auto_reconnect; | ||
config.host = uri.hostname; | ||
config.port = Number(uri.port) || DEFAULT_PORT; | ||
if(uri.pathname) { | ||
config.port = parseInt(uri.port, 10) || DEFAULT_PORT; | ||
if (uri.pathname) { | ||
config.database = uri.pathname.replace(/\//g, ''); | ||
} | ||
config.options = {}; | ||
config.options['auto_reconnect'] = toBool(serverOptions['auto_reconnect']); | ||
config.options['poolSize'] = parseInt(serverOptions['poolSize'] || 1); | ||
config.options.auto_reconnect = toBool(serverOptions.auto_reconnect); | ||
config.options.poolSize = parseInt(serverOptions.poolSize || 1, 10); | ||
if (uri && uri.auth) { | ||
var auth = uri.auth, | ||
separator = auth.indexOf(':'); | ||
var auth = uri.auth; | ||
var separator = auth.indexOf(':'); | ||
config.username = auth.substr(0, separator); | ||
@@ -50,4 +75,7 @@ config.password = auth.substr(separator + 1); | ||
* | ||
* @param {String} serverUrl | ||
* @return {Server} | ||
* @api private | ||
*/ | ||
var parseServer = function(serverUrl) { | ||
var parseServer = function (serverUrl) { | ||
var config = parseUrl(serverUrl); | ||
@@ -60,3 +88,3 @@ return new Server(config.host, config.port, config.options); | ||
*/ | ||
for(var key in mongo) { | ||
for (var key in mongo) { | ||
exports[key] = mongo[key]; | ||
@@ -66,24 +94,34 @@ } | ||
/** | ||
* constructor SkinDb from serverUrls | ||
* constructor SkinDb from serverURLs | ||
* | ||
* repliSet: mongoskin.db(serverUrls, rs_options, db_options) | ||
* RepliSet: mongoskin.db(serverURLs, options) | ||
* | ||
* mongoskin.db(['192.168.0.1:27017/', '192.168.0.2/?auto_reconnect', '192.168.0.3/?auto_reconnect'], { | ||
* database: 'mydb' | ||
* }) | ||
* | ||
* single Server: mongoskin.db(dbUrl, db_options) | ||
* | ||
* ```js | ||
* mongoskin.db(['192.168.0.1:27017/', '192.168.0.2/?auto_reconnect', '192.168.0.3'], { database: 'mydb' }) | ||
* ``` | ||
* | ||
* Single Server: mongoskin.db(dbURL, options) | ||
* | ||
* ```js | ||
* mongoskin.db('192.168.0.1:27017/mydb') | ||
* ``` | ||
* | ||
* or | ||
* | ||
* ```js | ||
* mongoskin.db('192.168.0.1:27017', { database: 'mydb' }) | ||
* ``` | ||
* | ||
* @param {String} serverUrl | ||
* @param {Object} [options] | ||
* @return {SkinDb} | ||
* @api public | ||
*/ | ||
exports.db = function(serverUrl, options) { | ||
if(!options) { | ||
options = {}; | ||
} | ||
exports.db = function (serverUrl, options) { | ||
options = options || {}; | ||
var server, database; | ||
var server, database, config; | ||
if(Array.isArray(serverUrl)) { | ||
if(!options.database) { | ||
if (Array.isArray(serverUrl)) { | ||
if (!options.database) { | ||
throw new Error('Please provide a database in options to connect.'); | ||
@@ -95,20 +133,20 @@ } | ||
var servers = []; | ||
for(var i = 0; i < len; i++) { | ||
var config = parseUrl(serverUrl[i]); | ||
if(config.database || config.username) { | ||
for (var i = 0; i < len; i++) { | ||
config = parseUrl(serverUrl[i]); | ||
if (config.database || config.username) { | ||
console.log('MONGOSKIN:WARN: database or username found in RepliSet server URL, ' + serverUrl[i]); | ||
} | ||
servers.push( new Server(config.host, config.port, config.options) ); | ||
servers.push(new Server(config.host, config.port, config.options)); | ||
} | ||
server = new ReplSetServers(servers); | ||
} else { | ||
var config = parseUrl(serverUrl); | ||
if (!config.database) { | ||
config = parseUrl(serverUrl); | ||
database = options.database || config.database; | ||
if (!database) { | ||
throw new Error('Please provide a database to connect to.'); | ||
} | ||
database = config.database; | ||
server = new Server(config.host, config.port, config.options); | ||
if(options.username === undefined) { | ||
if (options.username === undefined) { | ||
options.username = config.username; | ||
@@ -126,18 +164,22 @@ options.password = config.password; | ||
* | ||
* @param select function(name) returns SkinDb | ||
* @param select `function(name)` returns SkinDb | ||
* | ||
* var router = mongoskin.router(function(name){ | ||
* select(name){ | ||
* case 'user': | ||
* case 'group': | ||
* return authDb; | ||
* default: | ||
* return appDb; | ||
* } | ||
* ```js | ||
* var router = mongoskin.router(function (name) { | ||
* swhich (name) { | ||
* case 'user': | ||
* case 'group': | ||
* return authDb; | ||
* default: | ||
* return appDb; | ||
* } | ||
* }); | ||
* | ||
* router.collection('user') | ||
* | ||
* ``` | ||
* | ||
* @param {Function(name)} select | ||
* @return {Router} | ||
* @api public | ||
*/ | ||
exports.router = function(select) { | ||
exports.router = function (select) { | ||
return new Router(select); | ||
@@ -149,9 +191,7 @@ }; | ||
*/ | ||
['server', 'db', 'collection', 'cursor', 'admin'].forEach(function(path) { | ||
var foo, module, name; | ||
module = require('./' + path); | ||
for (name in module) { | ||
foo = module[name]; | ||
exports[name] = foo; | ||
['server', 'db', 'collection', 'cursor', 'admin'].forEach(function (path) { | ||
var module = require('./' + path); | ||
for (var name in module) { | ||
exports[name] = module[name]; | ||
} | ||
}); |
@@ -1,24 +0,49 @@ | ||
var Router = exports.Router = function(select) { | ||
/*! | ||
* mongoskin - router.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
/** | ||
* Router | ||
* | ||
* @param {Function(name)} select | ||
* @constructor | ||
* @api public | ||
*/ | ||
var Router = exports.Router = function (select) { | ||
this._select = select; | ||
this._collections = {}; | ||
} | ||
}; | ||
Router.prototype.bind = function() { | ||
var args = Array.prototype.slice.call(arguments), | ||
name = args[0]; | ||
/** | ||
* Bind custom methods | ||
* | ||
* @param {String} name, collection name. | ||
* @param {Object} [options] | ||
* @return {Router} this | ||
* @api public | ||
*/ | ||
Router.prototype.bind = function (name, options) { | ||
var args = Array.prototype.slice.call(arguments); | ||
var database = this._select(name); | ||
var coll = database.bind.apply(database, args); | ||
this._collections[name] = coll; | ||
var collection = database.bind.apply(database, args); | ||
this._collections[name] = collection; | ||
Object.defineProperty(this, name, { | ||
value: coll, | ||
writable: false, | ||
enumerable: true | ||
value: collection, | ||
writable: false, | ||
enumerable: true | ||
}); | ||
return this; | ||
}; | ||
Router.prototype.collection = function(name) { | ||
Router.prototype.collection = function (name) { | ||
return this._collections[name] || (this._collections[name] = this._select(name).collection(name)); | ||
}; |
@@ -1,15 +0,29 @@ | ||
var __slice = Array.prototype.slice, | ||
mongodb = require('mongodb'), | ||
Db = mongodb.Db, | ||
Server = mongodb.Server, | ||
SkinDb = require('./db').SkinDb; | ||
/*! | ||
* mongoskin - server.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var mongodb = require('mongodb'); | ||
var Db = mongodb.Db; | ||
var Server = mongodb.Server; | ||
var SkinDb = require('./db').SkinDb; | ||
/** | ||
* Construct SkinServer with native Server | ||
* | ||
* @param server | ||
* @param {Server} server | ||
* @constructor | ||
* @api public | ||
*/ | ||
var SkinServer = exports.SkinServer = function(server) { | ||
var SkinServer = exports.SkinServer = function (server) { | ||
this.server = server; | ||
this._cache_ = []; | ||
this._cache_ = {}; | ||
}; | ||
@@ -20,17 +34,17 @@ | ||
* | ||
* @param name database name | ||
* | ||
* @return SkinDb | ||
* | ||
* TODO add options | ||
* @param {String} name database name | ||
* @param {Object} [options] | ||
* @return {SkinDb} | ||
* @api public | ||
*/ | ||
SkinServer.prototype.db = function(name, options) { | ||
var key = (username || '') + '@' + name; | ||
SkinServer.prototype.db = function (name, options) { | ||
options = options || {}; | ||
var username = options.username || ''; | ||
var key = username + '@' + name; | ||
var skinDb = this._cache_[key]; | ||
if (!skinDb || skinDb.fail) { | ||
var username = options.username, | ||
password = options.password; | ||
var password = options.password; | ||
delete options.username; | ||
delete options.password; | ||
if(options.native_parser === undefined) { | ||
if (!options.native_parser) { | ||
options.native_parser = !! mongodb.BSONNative; | ||
@@ -37,0 +51,0 @@ } |
@@ -1,8 +0,82 @@ | ||
exports.error = function(err, args, name) { | ||
/*! | ||
* mongoskin - utils.js | ||
* | ||
* Copyright(c) 2011 - 2012 kissjs.org | ||
* Copyright(c) 2012 fengmk2 <fengmk2@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
"use strict"; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
var __slice = Array.prototype.slice; | ||
var EventEmitter = require('events').EventEmitter; | ||
var constant = require('./constant'); | ||
var STATE_OPEN = constant.STATE_OPEN; | ||
var STATE_OPENNING = constant.STATE_OPENNING; | ||
var STATE_CLOSE = constant.STATE_CLOSE; | ||
exports.inherits = require('util').inherits; | ||
exports.error = function (err, args, name) { | ||
var cb = args.pop(); | ||
if(cb && typeof cb === 'function') { | ||
cb(err) | ||
if (cb && typeof cb === 'function') { | ||
cb(err); | ||
} else { | ||
console.error("Error occured with no callback to handle it while calling " + name, err); | ||
} | ||
} | ||
}; | ||
/** | ||
* SkinObject | ||
* | ||
* @constructor | ||
* @api public | ||
*/ | ||
exports.SkinObject = function () { | ||
this.emitter = new EventEmitter(); | ||
this.state = STATE_CLOSE; | ||
}; | ||
/** | ||
* Skin method binding. | ||
* | ||
* @param {String} objName | ||
* @param {Function} obj | ||
* @param {String} nativeObjName | ||
* @param {String} methodName | ||
* @param {Function} method | ||
* @return {Function} | ||
*/ | ||
exports.bindSkin = function (objName, obj, nativeObjName, methodName, method) { | ||
if (typeof method !== 'function') { | ||
return; | ||
} | ||
return obj.prototype[methodName] = function () { | ||
var args = __slice.call(arguments); | ||
if (this.state === STATE_OPEN) { | ||
method.apply(this[nativeObjName], args); | ||
return this; | ||
} | ||
this.open(function (err, nativeObj) { | ||
if (err) { | ||
exports.error(err, args, objName + '.' + methodName); | ||
} else { | ||
return method.apply(nativeObj, args); | ||
} | ||
}); | ||
return this; | ||
}; | ||
}; | ||
exports.extend = function (destination, source) { | ||
for (var property in source) { | ||
destination[property] = source[property]; | ||
} | ||
return destination; | ||
}; | ||
exports.noop = function () {}; |
{ | ||
"name": "mongoskin", | ||
"description": "The future layer above node-mongodb-native", | ||
"version": "0.3.6", | ||
"version": "0.3.7", | ||
"author": "Gui Lin<guileen@gmail.com>", | ||
@@ -12,14 +12,13 @@ "repository": { | ||
"keywords": [ | ||
"mongodb" | ||
"mongodb", "database", "nosql" | ||
], | ||
"engines": { | ||
"node": ">=0.4.0" | ||
"node": ">= 0.4.0" | ||
}, | ||
"dependencies": { | ||
"mongodb": "1.0.x" | ||
"mongodb": ">= 0.9.8" | ||
}, | ||
"devDependencies": { | ||
"myconsole": ">=0.1.2", | ||
"expresso": "0.9.2", | ||
"should": "0.3.2" | ||
"mocha": "*", | ||
"should": "*" | ||
}, | ||
@@ -26,0 +25,0 @@ "directories": { |
447
Readme.md
@@ -1,10 +0,23 @@ | ||
## This project is a wrapper of node-mongodb-native | ||
# mongoskin | ||
* node-mongodb-native document http://christkv.github.com/node-mongodb-native/ | ||
[](http://travis-ci.org/kissjs/node-mongoskin) | ||
## How to validate input? | ||
This project is a wrapper of [node-mongodb-native](https://github.com/mongodb/node-mongodb-native). | ||
The api is same to node-mongodb-native, please see the [document](http://mongodb.github.com/node-mongodb-native/) first. | ||
I wrote a middleware to validate post data, [node-iform](https://github.com/guileen/node-iform) | ||
base on [node-validator](https://github.com/chriso/node-validator) | ||
## Test | ||
* test results: [test_results.md](https://github.com/kissjs/node-mongoskin/blob/master/test_results.md) | ||
* jscoverage: [**89%**](http://fengmk2.github.com/coverage/mongoskin.html) | ||
## Test pass [mongodb] versions | ||
* >= 0.9.8 | ||
* 1.0.x | ||
* 1.1.x | ||
```bash | ||
$ make test-version | ||
``` | ||
<a name='index'> | ||
@@ -83,3 +96,5 @@ | ||
npm install mongoskin | ||
```bash | ||
$ npm install mongoskin | ||
``` | ||
@@ -105,6 +120,8 @@ [Back to index](#index) | ||
var mongo = require('mongoskin'); | ||
mongo.db('localhost:27017/testdb').collection('blog').find().toArray(function(err, items){ | ||
console.dir(items); | ||
}) | ||
```js | ||
var mongo = require('mongoskin'); | ||
mongo.db('localhost:27017/testdb').collection('blog').find().toArray(function (err, items) { | ||
console.dir(items); | ||
}) | ||
``` | ||
@@ -118,4 +135,6 @@ <a name='quickstart-2'></a> | ||
var mongo = require('mongoskin'), | ||
db = mongo.db('localhost:27017/test?auto_reconnect'); | ||
```js | ||
var mongo = require('mongoskin'); | ||
var db = mongo.db('localhost:27017/test?auto_reconnect'); | ||
``` | ||
@@ -128,8 +147,10 @@ <a name='quickstart-3'></a> | ||
db.createCollection(...); | ||
db.collection('user').ensureIndex([['username', 1]], true, function(err, replies){}); | ||
db.collection('posts').hint = 'slug'; | ||
db.collection('posts').findOne({slug: 'whats-up'}, function(err, post){ | ||
// do something | ||
}); | ||
```js | ||
db.createCollection(...); | ||
db.collection('user').ensureIndex([['username', 1]], true, function (err, replies) {}); | ||
db.collection('posts').hint = 'slug'; | ||
db.collection('posts').findOne({slug: 'whats-up'}, function (err, post) { | ||
// do something | ||
}); | ||
``` | ||
@@ -141,5 +162,7 @@ <a name='quickstart-4'></a> | ||
db.collection('posts').find().toArray(function(err, posts){ | ||
// do something | ||
}); | ||
```js | ||
db.collection('posts').find().toArray(function (err, posts) { | ||
// do something | ||
}); | ||
``` | ||
@@ -156,24 +179,26 @@ <a name='quickstart-5'></a> | ||
db.bind('posts', { | ||
findTop10 : function(fn){ | ||
this.find({}, {limit:10, sort:[['views', -1]]}).toArray(fn); | ||
}, | ||
removeTagWith : function(tag, fn){ | ||
this.remove({tags:tag},fn); | ||
} | ||
}); | ||
```js | ||
db.bind('posts', { | ||
findTop10 : function (fn) { | ||
this.find({}, {limit:10, sort:[['views', -1]]}).toArray(fn); | ||
}, | ||
removeTagWith : function (tag, fn) { | ||
this.remove({tags:tag},fn); | ||
} | ||
}); | ||
db.bind('comments'); | ||
db.bind('comments'); | ||
db.collection('posts').removeTagWith('delete', function(err, replies){ | ||
//do something | ||
}); | ||
db.collection('posts').removeTagWith('delete', function (err, replies) { | ||
//do something | ||
}); | ||
db.posts.findTop10(function(err, topPosts){ | ||
//do something | ||
}); | ||
db.posts.findTop10(function (err, topPosts) { | ||
//do something | ||
}); | ||
db.comments.find().toArray(function(err, comments){ | ||
//do something | ||
}); | ||
db.comments.find().toArray(function (err, comments) { | ||
//do something | ||
}); | ||
``` | ||
@@ -200,9 +225,13 @@ [Back to index](#index) | ||
[*://][username:password@]host[:port][/database][?auto_reconnect[=true|false]]` | ||
``` | ||
[*://][username:password@]host[:port][/database][?auto_reconnect[=true|false]]` | ||
``` | ||
e.g. | ||
localhost/blog | ||
mongo://admin:pass@127.0.0.1:27017/blog?auto_reconnect | ||
127.0.0.1?auto_reconnect=false | ||
``` | ||
localhost/blog | ||
mongo://admin:pass@127.0.0.1:27017/blog?auto_reconnect | ||
127.0.0.1?auto_reconnect=false | ||
``` | ||
@@ -213,31 +242,38 @@ ### db(databaseUrl, db_options) | ||
var db = mongoskin.db('localhost:27017/testdb?auto_reconnect=true&poolSize=5'); | ||
```js | ||
var db = mongoskin.db('localhost:27017/testdb?auto_reconnect=true&poolSize=5'); | ||
``` | ||
for ReplSet server | ||
var db = mongoskin.db(['192.168.0.1:27017/?auto_reconnect=true', | ||
'192.168.0.2:27017/?auto_reconnect=true', | ||
'192.168.0.3:27017/?auto_reconnect=true'], | ||
{ | ||
database: 'testdb', | ||
retryMiliSeconds: 2000 | ||
}) | ||
```js | ||
var db = mongoskin.db([ | ||
'192.168.0.1:27017/?auto_reconnect=true', | ||
'192.168.0.2:27017/?auto_reconnect=true', | ||
'192.168.0.3:27017/?auto_reconnect=true' | ||
], { | ||
database: 'testdb', | ||
retryMiliSeconds: 2000 | ||
}); | ||
``` | ||
### router(select) | ||
select is function(collectionName) returns a database instance, means router collectionName to that database. | ||
select is `function(collectionName)` returns a database instance, means router collectionName to that database. | ||
var db = mongo.router(function(coll_name){ | ||
switch(coll_name) { | ||
case 'user': | ||
case 'message': | ||
return mongo.db('192.168.1.3/auth_db'); | ||
default: | ||
return mongo.db('192.168.1.2/app_db'); | ||
} | ||
}); | ||
db.bind('user', require('./shared-user-methods')); | ||
var users = db.user; //auth_db.user | ||
var messages = db.collection('message'); // auth_db.message | ||
var products = db.collection('product'); //app_db.product | ||
```js | ||
var db = mongo.router(function (coll_name) { | ||
switch(coll_name) { | ||
case 'user': | ||
case 'message': | ||
return mongo.db('192.168.1.3/auth_db'); | ||
default: | ||
return mongo.db('192.168.1.2/app_db'); | ||
} | ||
}); | ||
db.bind('user', require('./shared-user-methods')); | ||
var users = db.user; //auth_db.user | ||
var messages = db.collection('message'); // auth_db.message | ||
var products = db.collection('product'); //app_db.product | ||
``` | ||
@@ -334,8 +370,10 @@ ### classes extends frome node-mongodb-native | ||
db.bind('book', { | ||
firstBook: function(fn){ | ||
this.findOne(fn); | ||
} | ||
}); | ||
db.book.firstBook(function(err, book){}); | ||
```js | ||
db.bind('book', { | ||
firstBook: function (fn) { | ||
this.findOne(fn); | ||
} | ||
}); | ||
db.book.firstBook(function (err, book) {}); | ||
``` | ||
@@ -366,3 +404,5 @@ ### all the methods from Db.prototype | ||
db.bson_serializer.ObjectID.createFromHexString(hex); | ||
```js | ||
db.bson_serializer.ObjectID.createFromHexString(hex); | ||
``` | ||
@@ -376,6 +416,8 @@ See [ObjectID.createFromHexString](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/bson/bson.js#L548) | ||
checkCollectionName(collectionName) | ||
options(callback) | ||
rename(collectionName, callback) | ||
drop(callback) | ||
```js | ||
checkCollectionName(collectionName) | ||
options(callback) | ||
rename(collectionName, callback) | ||
drop(callback) | ||
``` | ||
@@ -386,7 +428,9 @@ <a name='inherit-indexes'> | ||
createIndex (fieldOrSpec, unique, callback) | ||
ensureIndex (fieldOrSpec, unique, callback) | ||
indexInformation (callback) | ||
dropIndex (indexName, callback) | ||
dropIndexes (callback) | ||
```js | ||
createIndex(fieldOrSpec, unique, callback) | ||
ensureIndex(fieldOrSpec, unique, callback) | ||
indexInformation(callback) | ||
dropIndex(indexName, callback) | ||
dropIndexes(callback) | ||
``` | ||
@@ -405,5 +449,7 @@ See [mongodb-native indexes](https://github.com/christkv/node-mongodb-native/blob/master/docs/indexes.md) | ||
collection.find(..., function(err, cursor){ | ||
cursor.toArray(callback); | ||
}); | ||
```js | ||
collection.find(..., function (err, cursor) { | ||
cursor.toArray(callback); | ||
}); | ||
``` | ||
@@ -416,5 +462,7 @@ See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L348) | ||
collection.find(..., function(err, cursor){ | ||
cursor.each(callback); | ||
}); | ||
```js | ||
collection.find(..., function (err, cursor) { | ||
cursor.each(callback); | ||
}); | ||
``` | ||
@@ -427,3 +475,5 @@ See [Collection.find](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L348) | ||
collection.findOne({_id, ObjectID.createFromHexString(id)}, ..., callback); | ||
```js | ||
collection.findOne({_id, ObjectID.createFromHexString(id)}, ..., callback); | ||
``` | ||
@@ -440,9 +490,9 @@ See [Collection.findOne](https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L417) | ||
// callback | ||
db.book.find({}, function(err, cursor){/* do something */}); | ||
// future SkinCursor | ||
db.book.find().toArray(function(err, books){/* do something */}); | ||
```js | ||
// callback | ||
db.book.find({}, function (err, cursor) {/* do something */}); | ||
// future SkinCursor | ||
db.book.find().toArray(function (err, books) {/* do something */}); | ||
``` | ||
#### normalizeHintField(hint) | ||
@@ -452,29 +502,33 @@ | ||
/** | ||
* Various argument possibilities | ||
* 1 callback | ||
* 2 selector, callback, | ||
* 2 callback, options // really?! | ||
* 3 selector, fields, callback | ||
* 3 selector, options, callback | ||
* 4,selector, fields, options, callback | ||
* 5 selector, fields, skip, limit, callback | ||
* 6 selector, fields, skip, limit, timeout, callback | ||
* | ||
* Available options: | ||
* limit, sort, fields, skip, hint, explain, snapshot, timeout, tailable, batchSize | ||
*/ | ||
```js | ||
/** | ||
* Various argument possibilities | ||
* 1 callback | ||
* 2 selector, callback, | ||
* 2 callback, options // really?! | ||
* 3 selector, fields, callback | ||
* 3 selector, options, callback | ||
* 4,selector, fields, options, callback | ||
* 5 selector, fields, skip, limit, callback | ||
* 6 selector, fields, skip, limit, timeout, callback | ||
* | ||
* Available options: | ||
* limit, sort, fields, skip, hint, explain, snapshot, timeout, tailable, batchSize | ||
*/ | ||
``` | ||
#### findAndModify(query, sort, update, options, callback) | ||
/** | ||
Fetch and update a collection | ||
query: a filter for the query | ||
sort: if multiple docs match, choose the first one in the specified sort order as the object to manipulate | ||
update: an object describing the modifications to the documents selected by the query | ||
options: | ||
remove: set to a true to remove the object before returning | ||
new: set to true if you want to return the modified object rather than the original. Ignored for remove. | ||
upsert: true/false (perform upsert operation) | ||
**/ | ||
```js | ||
/** | ||
Fetch and update a collection | ||
query: a filter for the query | ||
sort: if multiple docs match, choose the first one in the specified sort order as the object to manipulate | ||
update: an object describing the modifications to the documents selected by the query | ||
options: | ||
remove: set to a true to remove the object before returning | ||
new: set to true if you want to return the modified object rather than the original. Ignored for remove. | ||
upsert: true/false (perform upsert operation) | ||
**/ | ||
``` | ||
@@ -489,27 +543,34 @@ #### findOne(queryObject, options, callback) | ||
e.g. ``` | ||
var map = function(){ | ||
emit(test(this.timestamp.getYear()), 1); | ||
} | ||
var reduce = function(k, v){ | ||
count = 0; | ||
for(i = 0; i < v.length; i++) { | ||
count += v[i]; | ||
} | ||
return count; | ||
} | ||
collection.mapReduce(map, reduce, {scope:{test:new client.bson_serializer.Code(t.toString())}}, function(err, collection) { | ||
collection.find(function(err, cursor) { | ||
cursor.toArray(function(err, results) { | ||
test.equal(2, results[0].value) | ||
finished_test({test_map_reduce_functions_scope:'ok'}); | ||
}) | ||
}) | ||
``` | ||
e.g. | ||
```js | ||
var map = function () { | ||
emit(test(this.timestamp.getYear()), 1); | ||
} | ||
var reduce = function (k, v){ | ||
count = 0; | ||
for (i = 0; i < v.length; i++) { | ||
count += v[i]; | ||
} | ||
return count; | ||
} | ||
var options = {scope: {test: new client.bson_serializer.Code(t.toString())}}; | ||
collection.mapReduce(map, reduce, options, function (err, collection) { | ||
collection.find(function (err, cursor) { | ||
cursor.toArray(function (err, results) { | ||
test.equal(2, results[0].value) | ||
finished_test({test_map_reduce_functions_scope:'ok'}); | ||
}) | ||
}) | ||
``` | ||
#### group(keys, condition, initial, reduce, command, callback) | ||
e.g. `collection.group([], {}, {"count":0}, "function (obj, prev) { prev.count++; }", true, function(err, results) {` | ||
e.g. | ||
```js | ||
collection.group([], {}, {"count":0}, "function (obj, prev) { prev.count++; }", true, function(err, results) {}); | ||
``` | ||
#### count(query, callback) | ||
@@ -530,15 +591,17 @@ #### distinct(key, query, callback) | ||
/** | ||
Update a single document in this collection. | ||
spec - a associcated array containing the fields that need to be present in | ||
the document for the update to succeed | ||
```js | ||
/** | ||
Update a single document in this collection. | ||
spec - a associcated array containing the fields that need to be present in | ||
the document for the update to succeed | ||
document - an associated array with the fields to be updated or in the case of | ||
a upsert operation the fields to be inserted. | ||
document - an associated array with the fields to be updated or in the case of | ||
a upsert operation the fields to be inserted. | ||
Options: | ||
upsert - true/false (perform upsert operation) | ||
multi - true/false (update all documents matching spec) | ||
safe - true/false (perform check if the operation failed, required extra call to db) | ||
**/ | ||
Options: | ||
upsert - true/false (perform upsert operation) | ||
multi - true/false (update all documents matching spec) | ||
safe - true/false (perform check if the operation failed, required extra call to db) | ||
**/ | ||
``` | ||
@@ -551,7 +614,8 @@ #### update(spec, document, options, callback) | ||
collection.update({_id, ObjectID.createFromHexString(id)}, ..., callback); | ||
```js | ||
collection.update({_id, ObjectID.createFromHexString(id)}, ..., callback); | ||
``` | ||
See [Collection.update](https://github.com/christkv/node-mongodb-native/blob/master/docs/insert.md) | ||
<a name='inherit-removing'> | ||
@@ -577,15 +641,72 @@ | ||
sort(keyOrList, [direction], [callback]) | ||
limit(limit, [callback]) | ||
skip(skip, [callback]) | ||
batchSize(skip, [callback]) | ||
```js | ||
sort(keyOrList, [direction], [callback]) | ||
limit(limit, [callback]) | ||
skip(skip, [callback]) | ||
batchSize(skip, [callback]) | ||
toArray(callback) | ||
each(callback) | ||
count(callback) | ||
nextObject(callback) | ||
getMore(callback) | ||
explain(callback) | ||
toArray(callback) | ||
each(callback) | ||
count(callback) | ||
nextObject(callback) | ||
getMore(callback) | ||
explain(callback) | ||
``` | ||
[Back to index](#index) | ||
[Back to index](#index) | ||
## How to validate input? | ||
I wrote a middleware to validate post data, [node-iform](https://github.com/guileen/node-iform) | ||
base on [node-validator](https://github.com/chriso/node-validator) | ||
## Authors | ||
Below is the output from `git-summary`. | ||
project: node-mongoskin | ||
commits: 112 | ||
active : 54 days | ||
files : 39 | ||
authors: | ||
49 Lin Gui 43.8% | ||
34 guilin 桂林 30.4% | ||
9 fengmk2 8.0% | ||
5 guilin 4.5% | ||
2 François de Metz 1.8% | ||
2 Paul Gebheim 1.8% | ||
2 Gui Lin 1.8% | ||
1 humanchimp 0.9% | ||
1 Aneil Mallavarapu 0.9% | ||
1 wmertens 0.9% | ||
1 Harvey McQueen 0.9% | ||
1 Joe Faber 0.9% | ||
1 Matt Perpick 0.9% | ||
1 Quang Van 0.9% | ||
1 Rakshit Menpara 0.9% | ||
1 Wout Mertens 0.9% | ||
## License | ||
(The MIT License) | ||
Copyright (c) 2011 - 2012 kissjs.org | ||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
'Software'), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
98380
79.93%2
-33.33%39
56%2116
72.17%691
21.02%2
100%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
Updated