New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mongoskin

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongoskin - npm Package Compare versions

Comparing version

to
0.3.7

.jshintrc

4

examples/config.js
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": {

@@ -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/
[![Build Status](https://secure.travis-ci.org/kissjs/node-mongoskin.png)](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