├── index.js ├── test ├── mocha.opts ├── tools │ └── keyfile.txt ├── utils │ ├── pedding.js │ └── server_manager.js ├── db.js ├── runner.js ├── admin.js ├── helper.js ├── grid_store.js ├── cursor.js ├── utils.js └── collection.js ├── .npmignore ├── examples ├── config.js ├── insert.js ├── admin.js ├── gridfs.js ├── close.js ├── replset.js ├── update.js ├── generateId.js └── replSetBenchmark.js ├── .gitignore ├── .travis.yml ├── lib ├── constant.js ├── mongo_client.js ├── helper.js ├── admin.js ├── cursor.js ├── index.js ├── grid_store.js ├── db.js ├── utils.js └── collection.js ├── Makefile ├── .jshintrc ├── AUTHORS ├── LICENSE ├── package.json ├── History.md ├── Readme.md └── test_results.md /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/'); 2 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | -R spec 2 | --require should 3 | --timeout 2500 4 | -------------------------------------------------------------------------------- /test/tools/keyfile.txt: -------------------------------------------------------------------------------- 1 | THIS IS A SECRET KEYFILE FOR REPLICA SETS BWAHAHAHAH 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | data/ 2 | deps/ 3 | coverage.html 4 | lib-cov 5 | test/ 6 | test_results.md 7 | -------------------------------------------------------------------------------- /examples/config.js: -------------------------------------------------------------------------------- 1 | var mongo = require('../'); 2 | 3 | exports.db = mongo.db('mongodb://localhost/test'); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | data/ 3 | deps/ 4 | coverage.html 5 | lib-cov 6 | out 7 | test_results.md 8 | 9 | coverage 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.12" 5 | script: make coveralls 6 | services: 7 | - mongodb 8 | -------------------------------------------------------------------------------- /examples/insert.js: -------------------------------------------------------------------------------- 1 | var db = require('./config').db; 2 | 3 | db.collection('test').insert({foo: 'bar'}, function(err, result) { 4 | console.log(result); 5 | db.collection('test').drop(); 6 | db.close(); 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /examples/admin.js: -------------------------------------------------------------------------------- 1 | var db = require('./config').db; 2 | 3 | db.admin().listDatabases(function(err, result){ 4 | if(err) { 5 | console.traceError(err); 6 | } 7 | console.log(result); 8 | db.close(); 9 | }) 10 | -------------------------------------------------------------------------------- /lib/constant.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - constant.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | exports.DEFAULT_PORT = 27017; 12 | 13 | exports.STATE_CLOSE = 0; 14 | exports.STATE_OPENNING = 1; 15 | exports.STATE_OPEN = 2; -------------------------------------------------------------------------------- /examples/gridfs.js: -------------------------------------------------------------------------------- 1 | var db = require('./config').db; 2 | 3 | var gs = db.gridStore('test.txt', 'w') 4 | gs.write('blablabla', function(err, reply) { 5 | gs.close(function(err, reply){ 6 | var gs = db.gridStore('test.txt', 'r') 7 | gs.read(function(err, reply){ 8 | console.log(reply.toString()); 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /examples/close.js: -------------------------------------------------------------------------------- 1 | var db = require('./config').db; 2 | 3 | db.collection('test').findOne({}, function(err, data) { 4 | if(!err) { 5 | console.log('db has open'); 6 | console.log(data); 7 | } 8 | }); 9 | 10 | process.on('SIGINT', function() { 11 | console.log('Recieve SIGINT'); 12 | db.close(function(){ 13 | console.log('database has closed'); 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /lib/mongo_client.js: -------------------------------------------------------------------------------- 1 | var mongodb = require('mongodb'); 2 | var MongoClient = mongodb.MongoClient; 3 | var utils = require('./utils'); 4 | 5 | var SkinDb = require('./db').SkinDb; 6 | 7 | var SkinMongoClient = utils.makeSkinClass(MongoClient, true); 8 | exports.SkinMongoClient = SkinMongoClient; 9 | 10 | SkinMongoClient.connect = function() { 11 | var args = [].slice.call(arguments); 12 | var db = new SkinDb(); 13 | db._connect_args = args; 14 | return db; 15 | } 16 | -------------------------------------------------------------------------------- /test/utils/pedding.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/utils/pedding.js 3 | * Copyright(c) 2012 fengmk2 4 | * MIT Licensed 5 | */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | module.exports = function (n, fn) { 14 | var called = false; 15 | return function (err) { 16 | if (called) { 17 | return; 18 | } 19 | if (err) { 20 | called = true; 21 | return fn(err); 22 | } 23 | --n || fn(); 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /examples/replset.js: -------------------------------------------------------------------------------- 1 | var mongo = require('../'); 2 | var Db = mongo.Db; 3 | var Server = mongo.Server; 4 | var ReplSetServers = mongo.ReplSetServers; 5 | 6 | var replSet = new ReplSetServers([ 7 | new Server('localhost', 30000), 8 | new Server('localhost', 30001), 9 | new Server('localhost', 30002) 10 | ]); 11 | var db = new Db('integration_test_', replSet, {w:0}); 12 | db.collection('article').find().toArray(function(err, data) { 13 | console.log(err && err.stack); 14 | console.log(data); 15 | 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /lib/helper.js: -------------------------------------------------------------------------------- 1 | var mongodb = require('mongodb'); 2 | var ObjectID = mongodb.ObjectID; 3 | 4 | /** 5 | * Convert to ObjectID. 6 | * 7 | * @param {String} hex 8 | * @return {ObjectID} 9 | */ 10 | exports.toObjectID = function (hex) { 11 | if (hex instanceof ObjectID) { 12 | return hex; 13 | } 14 | if (!hex || hex.length !== 24) { 15 | return hex; 16 | } 17 | return ObjectID.createFromHexString(hex); 18 | }; 19 | 20 | exports.isObjectID = function (idstr) { 21 | return ObjectID.isValid(idstr); 22 | }; 23 | -------------------------------------------------------------------------------- /test/db.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/db.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | var should = require('should'); 15 | var mongoskin = require('../'); 16 | var pedding = require('./utils/pedding'); 17 | var servermanager = require('./utils/server_manager'); 18 | 19 | exports.testWithDb = function(db) { 20 | describe('db.js', function () { 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /examples/update.js: -------------------------------------------------------------------------------- 1 | var db = require('./config').db; 2 | var articles = db.collection('articles'); 3 | articles.insert({foo: 'bar', val: 'val1'}, function(err, result) { 4 | 5 | console.log(result); 6 | articles.update({foo:'bar'}, {foo: 'bar', val:'val2'}, {strict: true}, function(err, result) { 7 | 8 | console.log(result); 9 | articles.find({foo: 'bar'}).toArray(function(err, docs){ 10 | 11 | console.log(docs); 12 | articles.drop(); 13 | db.close(); 14 | 15 | }); 16 | 17 | }) 18 | 19 | }); 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MONGOSKIN_REPLICASET = false 2 | NODE_BIN=./node_modules/.bin 3 | MOCHA=$(NODE_BIN)/mocha 4 | COVERALLS=$(NODE_BIN)/coveralls 5 | 6 | test: 7 | @$(MOCHA) -R spec 8 | 9 | test-debug: 10 | @$(MOCHA) -R spec debug 11 | 12 | test-replicaset: 13 | @MONGOSKIN_REPLICASET=true $(MOCHA) 14 | 15 | test-cov: 16 | @$(MOCHA) -R html-cov > coverage.html 17 | 18 | coveralls: 19 | npm run coverage 20 | cat ./coverage/lcov.info | ./node_modules/.bin/coveralls 21 | 22 | test-watch: 23 | @$(MOCHA) -w -R dot --growl 24 | 25 | .PHONY: test-cov test-replicaset test test-debug 26 | -------------------------------------------------------------------------------- /lib/admin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - admin.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | var Admin = require('mongodb/lib/admin'); 12 | var makeSkinClass = require('./utils').makeSkinClass; 13 | 14 | var SkinAdmin = exports.SkinAdmin = makeSkinClass(Admin, false, true); 15 | 16 | SkinAdmin.prototype._open = function(callback) { 17 | var skindb = this._construct_args[0]; 18 | skindb.open(function(err, p_db) { 19 | if(err) return callback(err); 20 | callback(null, p_db.admin()); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /examples/generateId.js: -------------------------------------------------------------------------------- 1 | var redis = require('redis').createClient() 2 | , shorten = require('shorten')(redis) 3 | , async = require('async') 4 | , db = require('./config').db 5 | ; 6 | 7 | db.bind('user'); 8 | 9 | function log(err) { 10 | if(err) { 11 | console.log(err.stack); 12 | } 13 | } 14 | 15 | function createUser(user, callback) { 16 | 17 | async.waterfall([ 18 | function(fn) { 19 | shorten.nextId('user', fn); 20 | } 21 | , function(uid, fn) { 22 | user.uid = uid; 23 | db.user.save(user, fn); 24 | } 25 | ], callback); 26 | 27 | } 28 | 29 | for(var i = 0; i<10; i++) { 30 | createUser({name: 'user' + i}, log); 31 | } 32 | -------------------------------------------------------------------------------- /lib/cursor.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - cursor.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * MIT Licensed 6 | */ 7 | 8 | "use strict"; 9 | 10 | /** 11 | * Module dependencies. 12 | */ 13 | 14 | var Cursor = require('mongodb').Cursor; 15 | var utils = require('./utils'); 16 | 17 | var SkinCursor = exports.SkinCursor = utils.makeSkinClass(Cursor); 18 | 19 | /** 20 | * Retrieve mongodb.Cursor instance. 21 | * 22 | * @param {Function(err, cursor)} callback 23 | * @return {SkinCursor} this 24 | * @api public 25 | */ 26 | SkinCursor.prototype._open = function (callback) { 27 | var self = this; 28 | this._skin_collection.open(function (err, collection) { 29 | if (err) return callback(err); 30 | var args = self._find_args.concat([callback]); 31 | collection.find.apply(collection, args); 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "phantom", 4 | "module", 5 | "require", 6 | "__dirname", 7 | "process", 8 | "console", 9 | "it", 10 | "describe", 11 | "before", 12 | "beforeEach", 13 | "after", 14 | "should", 15 | "rewire", 16 | "$" 17 | ], 18 | 19 | "browser": true, 20 | "node" : true, 21 | "es5": true, 22 | "bitwise": true, 23 | "curly": true, 24 | "eqeqeq": true, 25 | "forin": false, 26 | "immed": true, 27 | "latedef": true, 28 | "newcap": true, 29 | "noarg": true, 30 | "noempty": true, 31 | "nonew": true, 32 | "plusplus": false, 33 | "undef": true, 34 | "strict": true, 35 | "trailing": false, 36 | "globalstrict": true, 37 | "nonstandard": true, 38 | "white": false, 39 | "indent": 2, 40 | "expr": true, 41 | "multistr": true, 42 | "onevar": false 43 | } -------------------------------------------------------------------------------- /test/runner.js: -------------------------------------------------------------------------------- 1 | var mongo = require('../'); 2 | var MongoClient = mongo.MongoClient; 3 | var Db = mongo.Db; 4 | var Server = mongo.Server; 5 | 6 | require('./helper'); 7 | 8 | var connect_db = MongoClient.connect('mongodb://127.0.0.1:27017/connect_db'); 9 | var new_db = new Db('new_db', new Server('127.0.0.1', 27017), {safe:true}); 10 | 11 | function testDb(caseName, db) { 12 | describe(caseName, function() { 13 | ;[ 14 | require('./db'), 15 | require('./collection'), 16 | require('./cursor'), 17 | require('./admin'), 18 | require('./grid_store') 19 | ].forEach(function(mod) { 20 | mod.testWithDb(db); 21 | }) 22 | 23 | after(function (done) { 24 | db.close(done); 25 | }); 26 | }) 27 | } 28 | 29 | testDb('connect_db', connect_db); 30 | testDb('new_db', new_db); 31 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - index.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * MIT Licensed 6 | */ 7 | 8 | "use strict"; 9 | 10 | /** 11 | * Module dependencies. 12 | */ 13 | 14 | var mongo = require('mongodb'); 15 | 16 | /* 17 | * exports mongo classes ObjectID Long Code DbRef ... to mongoskin 18 | */ 19 | for (var key in mongo) { 20 | exports[key] = mongo[key]; 21 | } 22 | 23 | // exports.Foo = SkinFoo; 24 | ;['mongo_client', 'db', 'collection', 'cursor', 'admin', 'grid_store'].forEach(function(modPath){ 25 | var mod = require('./' + modPath); 26 | for(var name in mod) { 27 | if(name.indexOf('Skin') == 0) { 28 | exports[name.substring(4)] = mod[name]; 29 | } 30 | } 31 | }); 32 | 33 | exports.helper = require('./helper'); 34 | exports.utils = require('./utils'); 35 | 36 | exports.db = exports.MongoClient.connect; 37 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Total 12 contributors. 2 | # Ordered by date of first contribution. 3 | # Auto-generated (http://github.com/dtrejo/node-authors) on Tue Aug 14 2012 02:58:57 GMT+0800 (CST). 4 | 5 | Gui Lin (https://github.com/guileen) 6 | François de Metz (https://github.com/francois2metz) 7 | fengmk2 (http://fengmk2.github.com) 8 | Quang Van (https://github.com/quangv) 9 | Matt Perpick (https://github.com/clutchski) 10 | humanchimp (https://github.com/humanchimp) 11 | Joe Faber (https://github.com/jlfaber) 12 | Harvey McQueen (https://github.com/hmcqueen) 13 | Paul Gebheim (https://github.com/paulirish) 14 | Aneil Mallavarapu (https://github.com/amallavarapu) 15 | wmertens (https://github.com/wmertens) 16 | Rakshit Menpara (https://github.com/deltasquare4) 17 | -------------------------------------------------------------------------------- /test/admin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var should = require('should'); 4 | var Admin = require('../').Admin; // SkinAdmin 5 | var Db = require('../').Db; // SkinDb 6 | 7 | exports.testWithDb = function(db) { 8 | function testAdmin(descName, adminDb) { 9 | describe(descName, function() { 10 | it('should add the new user to the admin database', function(done) { 11 | adminDb.addUser('admin3', 'admin3', done); 12 | }); 13 | 14 | it('should authenticate using the newly added user', function(done) { 15 | adminDb.logout(function(err, result) { 16 | adminDb.authenticate('admin3', 'admin3', done); 17 | }); 18 | }) 19 | 20 | it('should remove user just added', function(done) { 21 | adminDb.removeUser('admin3', done); 22 | }) 23 | 24 | it('should ping', function(done) { 25 | adminDb.ping(function(error, res) { 26 | done(error && !!res); 27 | }); 28 | }); 29 | }); 30 | } 31 | 32 | testAdmin('db.db("admin")', db.admin()); 33 | testAdmin('new Admin(db)', new Admin(db)); 34 | } 35 | -------------------------------------------------------------------------------- /lib/grid_store.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var GridStore = require('mongodb').GridStore; 4 | var makeSkinClass = require('./utils').makeSkinClass; 5 | 6 | var SkinGridStore = exports.SkinGridStore = makeSkinClass(GridStore); 7 | 8 | SkinGridStore.prototype._open = function(callback) { 9 | var skin_db = this._construct_args[0]; 10 | var args = this._construct_args.slice(1); 11 | skin_db.open(function(err, p_db) { 12 | if(err) return callback(err); 13 | args = ([null, p_db]).concat(args); 14 | var ctor = GridStore.bind.apply(GridStore, args); 15 | var gridStore = new ctor(); 16 | gridStore.open(callback); 17 | }); 18 | } 19 | 20 | function bindStaticMethod(methodName) { 21 | SkinGridStore[methodName] = function(skindb) { 22 | var args = Array.prototype.slice.call(arguments); 23 | skindb.open(function(err, p_db) { 24 | args[0] = p_db; 25 | GridStore[methodName].apply(GridStore, args); 26 | }); 27 | } 28 | } 29 | 30 | bindStaticMethod('exist'); 31 | bindStaticMethod('list'); 32 | bindStaticMethod('read'); 33 | bindStaticMethod('readlines'); 34 | bindStaticMethod('unlink'); 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2011 - 2012 kissjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongoskin", 3 | "description": "The future layer above node-mongodb-native", 4 | "version": "2.1.0", 5 | "author": "Gui Lin ", 6 | "homepage": "https://github.com/kissjs/node-mongoskin", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/kissjs/node-mongoskin.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/kissjs/node-mongoskin/issues" 13 | }, 14 | "main": "./index.js", 15 | "keywords": [ 16 | "mongodb", 17 | "database", 18 | "nosql" 19 | ], 20 | "engines": { 21 | "node": ">= 0.4.0" 22 | }, 23 | "peerDependencies": { 24 | "mongodb": "^2.0" 25 | }, 26 | "devDependencies": { 27 | "istanbul": "0.3.17", 28 | "mocha": "~1.17.1", 29 | "coveralls": "~2.10.0", 30 | "mocha-lcov-reporter": "0.0.1", 31 | "travis-cov": "~0.2.5", 32 | "mongodb": "^2.0", 33 | "should": "~3.1.2" 34 | }, 35 | "scripts": { 36 | "test": "./node_modules/.bin/mocha", 37 | "coverage": "istanbul cover _mocha" 38 | }, 39 | "directories": { 40 | "example": "./examples", 41 | "lib": "./lib/mongoskin" 42 | }, 43 | "license": "MIT" 44 | } 45 | -------------------------------------------------------------------------------- /examples/replSetBenchmark.js: -------------------------------------------------------------------------------- 1 | 2 | var mongo = require('../'); 3 | 4 | var conf = { 5 | hosts: [ 6 | '127.0.0.1:27110/?auto_reconnect', 7 | '127.0.0.1:27111/?auto_reconnect' 8 | ], 9 | dataDB: 'test' 10 | }; 11 | 12 | var db = exports.db = mongo.db(conf.hosts, { 13 | database: conf.dataDB 14 | }); 15 | 16 | var noop = function() {}; 17 | 18 | db.bind('user'); 19 | // db.user.ensureIndex({ name: 1 }, { unique: true }, noop); 20 | // db.user.ensureIndex({ enable: 1 }, noop); 21 | // db.user.ensureIndex({ created_at: 1, enable: 1 }, noop); 22 | 23 | var counter = 0; 24 | setInterval(function () { 25 | db.user.findItems({ name: 'name_' + counter }, function (err, items) { 26 | if (err) { 27 | console.error('findItems user error', err); 28 | } 29 | if (items) { 30 | console.log('total: %d users', items.length); 31 | } 32 | }); 33 | db.user.insert({ 34 | name: 'name_' + counter, 35 | createtime: new Date() 36 | }, function(err, user) { 37 | if (err) { 38 | console.error('insert user error', err); 39 | } 40 | if (user && user[0]) { 41 | console.log('new: %d %s', counter, user[0]._id); 42 | } 43 | }); 44 | counter++; 45 | }, 10); 46 | -------------------------------------------------------------------------------- /test/helper.js: -------------------------------------------------------------------------------- 1 | var mongo = require('../'); 2 | var ObjectID = mongo.ObjectID; 3 | var helper = mongo.helper; 4 | 5 | describe('helper.id()', function () { 6 | it('should convert string id to ObjectID success', function () { 7 | var id = '4ec4b2b9f44a927223000001'; 8 | id = helper.toObjectID(id); 9 | id.should.be.instanceof(ObjectID); 10 | id = helper.toObjectID(id); 11 | id.should.be.instanceof(ObjectID); 12 | id = '4ec4b2b9f44a927223000foo'; 13 | id = helper.toObjectID(id); 14 | id.should.be.instanceof(ObjectID); 15 | }); 16 | it('should return source id when id length !== 24', function () { 17 | var ids = [123, '4ec4b2b9f44a92722300000', 'abc', '4ec4b2b9f44a927223000f00123123']; 18 | ids.forEach(function (id) { 19 | helper.toObjectID(id).should.equal(id); 20 | }); 21 | }); 22 | }); 23 | 24 | describe('helper.isObjectID()', function () { 25 | it('should return false when ID is not valid hex', function () { 26 | var id = '54da050b878fd5d462672bea'; 27 | var isID = helper.isObjectID(id); 28 | isID.should.equal(true); 29 | id = 'h4da050b878fd5d462672bea'; 30 | isID = helper.isObjectID(id); 31 | isID.should.equal(false); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/utils/server_manager.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/utils/server_manager.js 3 | * Copyright(c) 2012 fengmk2 4 | * MIT Licensed 5 | */ 6 | 7 | "use strict"; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var MONGOSKIN_REPLICASET = process.env.MONGOSKIN_REPLICASET === 'true'; 14 | var RS = null; 15 | var RS_primary = null; 16 | 17 | exports.ensureUp = function (callback) { 18 | var ReplicaSetManager = require('../../deps/mongodb/test/tools/replica_set_manager').ReplicaSetManager; 19 | var ServerManager = require('../../deps/mongodb/test/tools/server_manager').ServerManager; 20 | // Create instance of replicaset manager but only for the first call 21 | if (!RS) { 22 | if (!MONGOSKIN_REPLICASET) { 23 | RS = new ServerManager(); 24 | RS.start(true, {purgedirectories: true}, function (err) { 25 | RS_primary = '127.0.0.1:' + RS.port; 26 | callback(err, RS, RS_primary); 27 | }); 28 | } else { 29 | RS = new ReplicaSetManager({retries: 120, secondary_count: 1, passive_count: 0, arbiter_count: 1}); 30 | RS.startSet(true, function (err, result) { 31 | RS.primary(function (err, primary) { 32 | RS_primary = primary; 33 | callback(err, RS, RS_primary); 34 | }); 35 | }); 36 | } 37 | process.on('exit', function () { 38 | console.log('process exit, stop mongod...'); 39 | RS.killAll(function () {}); 40 | }); 41 | } else { 42 | callback(null, RS, RS_primary); 43 | } 44 | }; 45 | 46 | exports.ensureDown = function (callback) { 47 | callback(); 48 | // if (RS) { 49 | // RS.killAll(callback); 50 | // } else { 51 | // callback(); 52 | // } 53 | }; 54 | 55 | exports.MONGOSKIN_REPLICASET = MONGOSKIN_REPLICASET; 56 | -------------------------------------------------------------------------------- /test/grid_store.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var should = require('should'); 4 | var GridStore = require('../').GridStore; // SkinGridStore 5 | var Db = require('../').Db; // SkinDb 6 | var ObjectID = require('../').ObjectID; 7 | var constant = require('../lib/constant'); 8 | var assert = require('assert'); 9 | 10 | exports.testWithDb = function(db) { 11 | // Our file ID 12 | var fileId = new ObjectID(); 13 | 14 | describe('grid_store.js', function() { 15 | // Open a new file 16 | var gridStore = new GridStore(db, fileId, 'w'); 17 | var originData = 'Hello world'; 18 | it('should write data to file', function(done) { 19 | // Write a text string 20 | gridStore.write(originData, function(err) { 21 | gridStore.close(done); 22 | }); 23 | }); 24 | 25 | it('should read file', function (done) { 26 | // use mongoskin style to create gridStore 27 | db.gridStore(fileId, 'r').read(function(err, data) { 28 | should.not.exist(err); 29 | data.toString().should.equal(originData); 30 | done(); 31 | }) 32 | }); 33 | 34 | it('should execute GridStore static methods', function(done) { 35 | GridStore.exist(db, fileId, done) 36 | }) 37 | 38 | // it('should unlink the file', function(done) { 39 | // // reuse previous write mode gridStore; 40 | // gridStore.unlink(function(err, result) { 41 | // assert.equal(null, err); 42 | 43 | // // Verify that the file no longer exists 44 | // GridStore.exist(db, fileId, function(err, result) { 45 | // assert.equal(null, err); 46 | // assert.equal(false, result); 47 | // done(err); 48 | // }); 49 | // }); 50 | // }) 51 | 52 | }) 53 | }; 54 | -------------------------------------------------------------------------------- /lib/db.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - db.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | * TODO db.gridfs() 14 | */ 15 | 16 | var mongodb = require('mongodb'); 17 | var Db = mongodb.Db; 18 | var MongoClient = mongodb.MongoClient; 19 | var utils = require('./utils'); 20 | var SkinAdmin = require('./admin').SkinAdmin; 21 | var SkinCollection = require('./collection').SkinCollection; 22 | var SkinGridStore = require('./grid_store').SkinGridStore; 23 | 24 | /** 25 | * Constructor 26 | */ 27 | var SkinDb = exports.SkinDb = utils.makeSkinClass(Db, true); 28 | 29 | SkinDb.prototype._open = function(callback) { 30 | // TODO authenticate support 31 | if(this._native) { 32 | this._native.open(callback); 33 | } else if(this._connect_args) { 34 | var args = this._connect_args.concat(callback); 35 | MongoClient.connect.apply(MongoClient, args); 36 | } 37 | } 38 | 39 | /** 40 | * Create or retrieval skin collection 41 | * 42 | * @param {String} name, the collection name. 43 | * @param {Object} [options] collection options. 44 | * @return {SkinCollection} 45 | * @api public 46 | */ 47 | SkinDb.prototype.collection = function (name, options) { 48 | // Ooops, no extended mthods like findById etc. 49 | // if(this.isOpen() && (!options || !options.strict) && !callback) { 50 | // // mongodb now support collection without callback 51 | // // see: http://mongodb.github.io/node-mongodb-native/api-generated/db.html#collection 52 | // return this._native.collection(name, options); 53 | // } 54 | var collection = new SkinCollection(); 55 | collection._skin_db = this; 56 | collection._collection_args = [name, options]; 57 | return collection; 58 | }; 59 | 60 | /** 61 | * @param {String} name the collection name 62 | * @param {Object} [options] collection options 63 | * @return {SkinCollection} collection 64 | */ 65 | SkinDb.prototype.bind = function (name, options) { 66 | return this[name] = this.collection(name, options); 67 | } 68 | 69 | SkinDb.prototype._admin = SkinDb.prototype.admin; 70 | SkinDb.prototype.admin = function () { 71 | return new SkinAdmin(this); 72 | } 73 | 74 | SkinDb.prototype.gridStore = function () { 75 | var skinGridStore = new SkinGridStore(); 76 | var args = Array.prototype.slice.call(arguments); 77 | args.unshift(this); 78 | skinGridStore._construct_args = args; 79 | return skinGridStore; 80 | } 81 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2.0.1 / 2015-10-09 2 | ================== 3 | * Return full admin class rather than just admin collection when calling `.admin()` #177 4 | 5 | 2.0.0 / 2015-09-21 6 | ================== 7 | * Support for mongodb driver v2.x 8 | * The `Grid` class [was removed in mongodb driver 2.0](https://github.com/mongodb/node-mongodb-native/blob/2.0/HISTORY.md#200-alpha1-2014-09-08) and so `mongoskin.Grid` is gone as well. 9 | * `utils.makeSkinClass()`'s optional third parameter `isSingle` is removed. 10 | * `db.collection()` no longer accepts a callback. Use `var collection = db.collection('collname');` instead. 11 | 12 | 0.6.1 / 2013-11-24 13 | ================== 14 | 15 | * Merge pull request #122 from Philmod/older-mongodb 16 | * older version of mongodb 17 | * Merge pull request #108 from fresheneesz/patch-1 18 | * Merge pull request #114 from nemtsov/patch-1 19 | * fix typo: this.hit -> this.hint 20 | * Vastly improving the documentation around the mongoskin.db method 21 | 22 | 0.6.0 / 2013-07-16 23 | ================== 24 | 25 | * changed version in package.json to 1.3.x for mongodb 26 | * Upgraded the mongo db version to 1.3.x. Mixing mongodb 1.2.x which mongoskin 0.5.0 depends on and latest mongodb 1.3.x causes Mongodb connection timeout problems in replication environment. 27 | * Use HTTPS so GitHub doesn't cache dependency badge 28 | * add Dependencies status image 29 | * Corrected repository URL in package.json 30 | * Documentation improvements 31 | * add 0.9 version test 32 | 33 | 0.5.0 / 2012-12-29 34 | ================== 35 | 36 | * fixed unsafe mode warnning log 37 | * Merge pull request #84 from kingpearl/master 38 | * MongoDB 1.2.x support 39 | * Merge pull request #73 from jockster/master 40 | * Merge pull request #75 from voke/patch-1 41 | * Fix typo 42 | * fixed bind() test cases; 43 | * Minor error in readme. Now updated 44 | * Updated readme according to issue #72 45 | 46 | 0.3.4 / 2011-03-24 47 | * fix global leaks 48 | 49 | 0.3.3 / 2011-03-15 50 | ================== 51 | * Add rootCollection option to SkinGridStore.exist 52 | 53 | 0.3.2 / 2011-03-01 54 | ================== 55 | * exports all classes of node-mongodb-native 56 | 57 | 0.3.1 / 2011-02-26 58 | ================== 59 | * bug fix #33 60 | 61 | 0.3.0 / 2011-01-19 62 | ================== 63 | * add ReplSet support 64 | * bug fix 65 | 66 | 0.2.3 / 2011-01-03 67 | ================== 68 | * add db.toObjectID 69 | * fix #25 for node-mongodb-native update 70 | 71 | 0.2.2 / 2011-12-02 72 | ================== 73 | * add bind support for embeded collections, e.g. db.bind('system.js') 74 | * add method `toId` to SkinDB 75 | * add property `ObjectID`, `bson_serializer` to SkinDB. 76 | * SkinCollection.prototype.id is now deprecated. 77 | 78 | 0.2.1 / 2011-11-18 79 | ================== 80 | * add ObjectId support for XXXXById 81 | 82 | 0.2.0 / 2011-11-06 83 | ================== 84 | * add SkinDB.gridfs 85 | 86 | 0.1.3 / 2011-05-24 87 | ================== 88 | * add SkinCollection.removeById 89 | 90 | 0.1.2 / 2011-04-30 91 | ================== 92 | * add mongoskin.router 93 | -------------------------------------------------------------------------------- /test/cursor.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/cursor.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | 15 | var should = require('should'); 16 | var mongoskin = require('../'); 17 | var SkinCursor = mongoskin.SkinCursor; 18 | var servermanager = require('./utils/server_manager'); 19 | 20 | exports.testWithDb = function(db) { 21 | 22 | describe('cursor.js', function () { 23 | // DO NOT use db.bind('testCursor') here, will not create SkinCursor if collection already open. 24 | // use db.collection('testCursor').find() to create SkinCursor every time 25 | before(function (done) { 26 | var docs = []; 27 | for (var i = 0; i < 100; i++) { 28 | docs.push({name: 'name ' + i, index: i}); 29 | } 30 | db.collection('testCursor').insert(docs, {safe:true}, function (err) { 31 | done(err); 32 | }); 33 | }); 34 | after(function (done) { 35 | db.collection('testCursor').drop(done); 36 | }); 37 | 38 | it('should call toArray()', function(done) { 39 | db.collection('testCursor').find().toArray(function(err, items) { 40 | should.not.exist(err); 41 | items.should.be.instanceof(Array).with.length(100); 42 | done(); 43 | }); 44 | }); 45 | it('should cursor.skip(10).limit(10).toArray() return 10 rows', function (done) { 46 | db.collection('testCursor').find().skip(10).limit(10).toArray(function (err, rows) { 47 | should.not.exist(err); 48 | should.exist(rows); 49 | rows.should.be.instanceof(Array).with.length(10); 50 | rows[0].name.should.equal('name 10'); 51 | rows[9].name.should.equal('name 19'); 52 | done(); 53 | }); 54 | }); 55 | 56 | it('should cursor.sort({index: -1}).skip(20).limit(10).toArray() return 10 rows', function (done) { 57 | db.collection('testCursor').find().sort({index: -1}).skip(20).limit(10).toArray(function (err, rows) { 58 | should.not.exist(err); 59 | should.exist(rows); 60 | rows.should.be.instanceof(Array).with.length(10); 61 | rows[0].name.should.equal('name 79'); 62 | rows[9].name.should.equal('name 70'); 63 | done(); 64 | }); 65 | }); 66 | 67 | it('should cursor.count() return 100', function (done) { 68 | db.collection('testCursor').find().count(function (err, count) { 69 | should.not.exist(err); 70 | count.should.equal(100); 71 | done(); 72 | }); 73 | }); 74 | 75 | it('should cursor.explain() return 100', function (done) { 76 | db.collection('testCursor').find({index: {$gt: 50}}).explain(function(err, result) { 77 | should.not.exist(err); 78 | if (result.executionStats) { 79 | // mongodb >= 3.0 80 | result.executionStats. 81 | should.have.property('totalDocsExamined'); 82 | result.executionStats. 83 | should.have.property('nReturned'); 84 | } else { 85 | result.should.have.property('cursor', 'BasicCursor'); 86 | } 87 | done(); 88 | }); 89 | }); 90 | }); 91 | } 92 | -------------------------------------------------------------------------------- /test/utils.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/utils.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | 15 | var utils = require('../').utils; 16 | var should = require('should'); 17 | 18 | describe('makeSkinClass', function () { 19 | 20 | function Foo() { 21 | this.isOpen = false; 22 | } 23 | 24 | Foo.prototype.chain = function() { 25 | return this; 26 | } 27 | 28 | Foo.prototype.get = function(arg, callback) { 29 | if(!this.isOpen) return callback(new Error('not open')); 30 | callback(null, arg); 31 | } 32 | 33 | Foo.prototype.makeError = function(code, callback) { 34 | var err = new Error('Error:' + code); 35 | err.code = code; 36 | callback(err); 37 | } 38 | 39 | var SkinFoo = utils.makeSkinClass(Foo); 40 | SkinFoo._bindSetter('isOpen'); 41 | SkinFoo._bindGetter('isOpen'); 42 | SkinFoo.prototype._open = function(callback) { 43 | var foo = new Foo(); 44 | var self = this; 45 | setTimeout(function() { 46 | if(self.willOpenError) { 47 | var err = new Error(); 48 | err.code = 'ERROPEN'; 49 | return callback(err) 50 | } else { 51 | foo.isOpen = true; 52 | callback(null, foo); 53 | } 54 | }, 10); 55 | } 56 | 57 | var skinFoo; 58 | before(function() { 59 | 60 | skinFoo = new SkinFoo(); 61 | 62 | }) 63 | 64 | describe('SkinClass', function() { 65 | it('should call native method', function(done) { 66 | skinFoo.get('echo', function(err, echo) { 67 | should.not.exists(err); 68 | echo.should.eql('echo'); 69 | done(); 70 | }); 71 | }); 72 | 73 | it('should callback error if error occused', function(done) { 74 | skinFoo.makeError('123', function(err) { 75 | err.code.should.eql('123'); 76 | done(); 77 | }) 78 | }) 79 | 80 | it('should chain operations', function(done) { 81 | skinFoo.chain().chain().chain().get('echo', done); 82 | }) 83 | 84 | it('should log open error if no callback', function(done) { 85 | var errFoo = new SkinFoo(); 86 | errFoo.willOpenError = true; 87 | errFoo.chain(); 88 | setTimeout(done, 15); 89 | }); 90 | 91 | it('should callback open error in chain callback', function(done) { 92 | var errFoo = new SkinFoo(); 93 | errFoo.willOpenError = true; 94 | errFoo.chain().chain().chain().get(function(err) { 95 | err.code.should.eql('ERROPEN'); 96 | done(); 97 | }); 98 | }) 99 | 100 | it('should get native property after open', function(done) { 101 | skinFoo.isOpen.should.be.true; 102 | done(); 103 | }) 104 | 105 | it('should set native property before open', function(done) { 106 | var foo = new SkinFoo(); 107 | foo.isOpen = 'abc'; 108 | foo.open(function(err, p_foo) { 109 | should.not.exists(err); 110 | p_foo.isOpen.should.eql('abc'); 111 | done(); 112 | }) 113 | }) 114 | 115 | it('should close just while openning', function(done) { 116 | var foo = new SkinFoo(); 117 | foo.chain().close(done); 118 | }) 119 | 120 | it('should call close even closing or closed', function(done) { 121 | var foo = new SkinFoo(); 122 | foo.chain().close().close(done); 123 | }) 124 | }) 125 | 126 | 127 | }); 128 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - utils.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | 15 | var __slice = Array.prototype.slice; 16 | var EventEmitter = require('events').EventEmitter; 17 | var constant = require('./constant'); 18 | var STATE_CLOSE = constant.STATE_CLOSE; 19 | var STATE_OPENNING = constant.STATE_OPENNING; 20 | var STATE_OPEN = constant.STATE_OPEN; 21 | 22 | exports.makeSkinClass = function makeSkinClass(NativeClass, useNativeConstructor) { 23 | 24 | function onError (err, args, name) { 25 | var cb = args.pop(); 26 | if (cb && typeof cb === 'function') { 27 | cb(err); 28 | } else { 29 | console.error("Error occured with no callback to handle it while calling " + name, err); 30 | } 31 | }; 32 | 33 | var skinClassName = 'Skin' + NativeClass.name; 34 | function SkinClass() { 35 | var args = __slice.call(arguments); 36 | this._construct_args = args; 37 | if(useNativeConstructor && arguments.length > 0) { 38 | args.unshift(null); 39 | var ctor = NativeClass.bind.apply(NativeClass, args); 40 | this._native = new ctor(); 41 | } else { 42 | this._native = null; 43 | } 44 | this._emitter = new EventEmitter(); 45 | this._emitter.setMaxListeners(50); 46 | this._state = STATE_CLOSE; 47 | this._init && this._init(); 48 | } 49 | SkinClass._class_name = skinClassName; 50 | 51 | function bindSkin(propName) { 52 | var fn; 53 | var desc = Object.getOwnPropertyDescriptor(NativeClass.prototype, propName); 54 | if(!desc) { 55 | // console.log('no desc', skinClassName, propName, desc); 56 | try{ 57 | fn = NativeClass.prototype[propName]; 58 | } catch(e) {} 59 | } else { 60 | fn = desc.value; 61 | } 62 | if(typeof fn == 'function') { 63 | SkinClass._bindMethod(propName); 64 | } else if(desc) { 65 | if (desc.get) { 66 | SkinClass._bindGetter(propName); 67 | } 68 | if (desc.set) { 69 | SkinClass._bindSetter(propName); 70 | } 71 | // } else { 72 | // this will never be called, so comment it. 73 | // console.log('no desc and no value', skinClassName, propName); 74 | } 75 | } 76 | 77 | SkinClass._bindMethod = function(propName) { 78 | SkinClass.prototype[propName] = function() { 79 | var args = __slice.apply(arguments); 80 | if (this._state == STATE_OPEN) { 81 | this._native[propName].apply(this._native, args); 82 | } else { 83 | this.open(function(err, p_native) { 84 | if (err) { 85 | onError(err, args, skinClassName + '.' + propName); 86 | } else { 87 | p_native[propName].apply(p_native, args); 88 | } 89 | }); 90 | } 91 | return this; 92 | } 93 | } 94 | 95 | SkinClass._bindGetter = function(propName) { 96 | SkinClass.prototype.__defineGetter__(propName, function() { 97 | return this._native && this._native[propName];// || this['_prop_' + propName]; 98 | }); 99 | } 100 | 101 | SkinClass._bindSetter = function(propName) { 102 | SkinClass.prototype.__defineSetter__(propName, function(value) { 103 | // this['_prop_' + propName] = value; 104 | this.open(function(err, p_native) { 105 | if(err) return onError(err, args, skinClassName + '.' + propName); 106 | p_native[propName] = value; 107 | }); 108 | }); 109 | } 110 | 111 | for(var propName in NativeClass.prototype) { 112 | if(propName[0] != '_') bindSkin(propName); 113 | } 114 | 115 | SkinClass.prototype.open = function(callback) { 116 | switch (this._state) { 117 | case STATE_OPEN: 118 | callback(null, this._native); 119 | break; 120 | case STATE_OPENNING: 121 | this._emitter.once('open', callback); 122 | break; 123 | default: 124 | this._emitter.once('open', callback); 125 | this._state = STATE_OPENNING; 126 | var self = this; 127 | this._open(function(err, p_native) { 128 | if (err) { 129 | self._state = STATE_CLOSE; 130 | } else { 131 | self._state = STATE_OPEN; 132 | self._native = p_native; 133 | } 134 | self._emitter.emit('open', err, p_native); 135 | }); 136 | } 137 | return this; 138 | } 139 | 140 | SkinClass.prototype.close = function (callback) { 141 | if (this._state === STATE_CLOSE) { 142 | callback && callback(); 143 | } else if (this._state === STATE_OPEN) { 144 | this._state = STATE_CLOSE; 145 | this._close(callback); 146 | } else if (this._state === STATE_OPENNING) { 147 | var self = this; 148 | this._emitter.once('open', function (err, db) { 149 | self.close(callback); 150 | }); 151 | } 152 | this._native = null; 153 | return this; 154 | } 155 | 156 | SkinClass.prototype._close = function(callback) { 157 | if(this._native.close) { 158 | this._native.close(callback) 159 | } else if(callback) { 160 | callback(); 161 | } 162 | } 163 | 164 | SkinClass.prototype.isOpen = function() { 165 | return this._state === STATE_OPEN; 166 | } 167 | 168 | return SkinClass; 169 | 170 | } 171 | -------------------------------------------------------------------------------- /lib/collection.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - collection.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | var __slice = Array.prototype.slice; 15 | var Collection = require('mongodb').Collection; 16 | var SkinCursor = require('./cursor').SkinCursor; 17 | var helper = require('./helper'); 18 | var utils = require('./utils'); 19 | 20 | /** 21 | * Constructor 22 | */ 23 | var SkinCollection = exports.SkinCollection = utils.makeSkinClass(Collection); 24 | 25 | /** 26 | * bind extend functions to collection 27 | * 28 | * e.g. 29 | * 30 | * db.bind('article').bind({ 31 | * getPostByAuthor: function(id, callback) { 32 | * this.findOne({author_id: id}, callback); 33 | * } 34 | * }); 35 | * 36 | */ 37 | SkinCollection.prototype.bind = function(extendObject) { 38 | for(var key in extendObject) { 39 | if(typeof extendObject[key] == 'function') { 40 | this[key] = extendObject[key].bind(this); 41 | } else { 42 | this[key] = extendObject[key]; 43 | } 44 | } 45 | } 46 | 47 | SkinCollection.prototype._open = function(callback) { 48 | var collection_args = this._collection_args.concat([callback]); 49 | this._skin_db.open(function(err, db) { 50 | if(err) return callback(err); 51 | db.collection.apply(db, collection_args); 52 | }); 53 | } 54 | 55 | /* 56 | * find is a special method, because it could return a SkinCursor instance 57 | */ 58 | SkinCollection.prototype._find = SkinCollection.prototype.find; 59 | 60 | /** 61 | * same args as find, but use Array as callback result but not use Cursor 62 | * 63 | * findItems(args, function (err, items) {}); 64 | * 65 | * same as 66 | * 67 | * find(args).toArray(function (err, items) {}); 68 | * 69 | * or using `mongodb.collection.find()` 70 | * 71 | * find(args, function (err, cursor) { 72 | * cursor.toArray(function (err, items) { 73 | * }); 74 | * }); 75 | * 76 | * @param {Object} [query] 77 | * @param {Object} [options] 78 | * @param {Function(err, docs)} callback 79 | * @return {SkinCollection} this 80 | * @api public 81 | */ 82 | SkinCollection.prototype.findItems = function (query, options, callback) { 83 | var args = __slice.call(arguments); 84 | var fn = args[args.length - 1]; 85 | args[args.length - 1] = function (err, cursor) { 86 | if (err) { 87 | return fn(err); 88 | } 89 | cursor.toArray(fn); 90 | }; 91 | this.find.apply(this, args); 92 | return this; 93 | }; 94 | 95 | /** 96 | * find and cursor.each(fn). 97 | * 98 | * @param {Object} [query] 99 | * @param {Object} [options] 100 | * @param {Function(err, item)} eachCallback 101 | * @return {SkinCollection} this 102 | * @api public 103 | */ 104 | SkinCollection.prototype.findEach = function (query, options, eachCallback) { 105 | var args = __slice.call(arguments); 106 | var fn = args[args.length - 1]; 107 | args[args.length - 1] = function (err, cursor) { 108 | if (err) { 109 | return fn(err); 110 | } 111 | cursor.each(fn); 112 | }; 113 | this.find.apply(this, args); 114 | return this; 115 | }; 116 | 117 | /** 118 | * Operate by object.`_id` 119 | * 120 | * @param {String} methodName 121 | * @param {String|ObjectID|Number} id 122 | * @param {Arguments|Array} args 123 | * @return {SkinCollection} this 124 | * @api private 125 | */ 126 | SkinCollection.prototype._operateById = function (methodName, id, args) { 127 | args = __slice.call(args); 128 | args[0] = {_id: helper.toObjectID(id)}; 129 | this[methodName].apply(this, args); 130 | return this; 131 | }; 132 | 133 | /** 134 | * Find one object by _id. 135 | * 136 | * @param {String|ObjectID|Number} id, doc primary key `_id` 137 | * @param {Function(err, doc)} callback 138 | * @return {SkinCollection} this 139 | * @api public 140 | */ 141 | SkinCollection.prototype.findById = function (id, callback) { 142 | return this._operateById('findOne', id, arguments); 143 | }; 144 | 145 | /** 146 | * Update doc by _id. 147 | * @param {String|ObjectID|Number} id, doc primary key `_id` 148 | * @param {Object} doc 149 | * @param {Function(err)} callback 150 | * @return {SkinCollection} this 151 | * @api public 152 | */ 153 | SkinCollection.prototype.updateById = function (id, doc, callback) { 154 | var oldCb = callback; 155 | var _this = this; 156 | if (callback) { 157 | callback = function(error, res) { 158 | oldCb.call(_this, error, !!res ? res.result : null); 159 | }; 160 | } 161 | return this._operateById('update', id, [id, doc, callback]); 162 | }; 163 | 164 | /** 165 | * Remove doc by _id. 166 | * @param {String|ObjectID|Number} id, doc primary key `_id` 167 | * @param {Function(err)} callback 168 | * @return {SkinCollection} this 169 | * @api public 170 | */ 171 | SkinCollection.prototype.removeById = function (id, callback) { 172 | var oldCb = callback; 173 | var _this = this; 174 | if (callback) { 175 | callback = function(error, res) { 176 | oldCb.call(_this, error, !!res ? res.result.n : null); 177 | }; 178 | } 179 | return this._operateById('remove', id, [id, callback]); 180 | }; 181 | 182 | /** 183 | * Creates a cursor for a query that can be used to iterate over results from MongoDB. 184 | * 185 | * @param {Object} query 186 | * @param {Object} options 187 | * @param {Function(err, docs)} callback 188 | * @return {SkinCursor|SkinCollection} if last argument is not a function, then returns a SkinCursor, 189 | * otherise return this 190 | * @api public 191 | */ 192 | SkinCollection.prototype.find = function (query, options, callback) { 193 | var args = __slice.call(arguments); 194 | if(this.isOpen()) { 195 | return this._native.find.apply(this._native, args); 196 | } 197 | if (args.length > 0 && typeof args[args.length - 1] === 'function') { 198 | this._find.apply(this, args); 199 | return this; 200 | } else { 201 | var cursor = new SkinCursor(); 202 | cursor._skin_collection = this; 203 | cursor._find_args = args; 204 | return cursor; 205 | } 206 | }; 207 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kissjs/node-mongoskin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | 3 | # mongoskin 4 | 5 | [![Build Status](https://secure.travis-ci.org/kissjs/node-mongoskin.svg)](http://travis-ci.org/kissjs/node-mongoskin) 6 | [![Dependencies](https://david-dm.org/kissjs/node-mongoskin.svg)](https://david-dm.org/kissjs/node-mongoskin) 7 | [![Coverage Status](https://coveralls.io/repos/kissjs/node-mongoskin/badge.svg?branch=master)](https://coveralls.io/r/kissjs/node-mongoskin?branch=master) 8 | [![NPM version](https://badge.fury.io/js/mongoskin.svg)](http://badge.fury.io/js/mongoskin) 9 | 10 | [![NPM](https://nodei.co/npm/mongoskin.png?downloads=true&stars=true)](https://nodei.co/npm/mongoskin/) 11 | 12 | [![NPM](https://nodei.co/npm-dl/mongoskin.png?months=6)](https://nodei.co/npm/mongoskin/) 13 | 14 | Install 15 | ======== 16 | 17 | ```bash 18 | $ npm install mongoskin 19 | ``` 20 | 21 | Usage 22 | ======== 23 | 24 | Use dburl 25 | 26 | ```js 27 | var mongo = require('mongoskin'); 28 | var db = mongo.db("mongodb://localhost:27017/integration_tests", {native_parser:true}); 29 | db.bind('article'); 30 | db.article.find().toArray(function(err, items) { 31 | db.close(); 32 | }); 33 | ``` 34 | 35 | Use ReplSet 36 | 37 | ```js 38 | var mongo = require('mongoskin'); 39 | var Server = mongo.Server; 40 | var Db = mongo.Db; 41 | 42 | var replSet = new ReplSetServers([ 43 | new Server('localhost', 30000), 44 | new Server('localhost', 30001), 45 | new Server('localhost', 30002), 46 | ]); 47 | 48 | var db = new Db('integration_test_', replSet, {w:0, native_parser: (process.env['TEST_NATIVE'] != null)}); 49 | // no need open and on('fullsetup', ...) 50 | db.collection('myconnection').find().setReadPreference(ReadPreference.SECONDARY).toArray(function(err, items) { 51 | db.close(); 52 | }); 53 | ``` 54 | 55 | Model helper: 56 | 57 | ```js 58 | var mongo = require('mongoskin'); 59 | var db = mongo.db("mongodb://localhost:27017/integration_tests", {native_parser:true}); 60 | db.bind('article').bind({ 61 | getByAuthor: function(author_id, callback) { 62 | this.findOne({author_id: author_id}, callback); 63 | } 64 | }); 65 | db.article.getByAuthor(author_id, function(err, article) { 66 | console.log(article); 67 | }); 68 | ``` 69 | 70 | ## Origin API part 71 | For detail API reference see [node mongodb API](http://mongodb.github.io/node-mongodb-native/). Mongoskin is just change the API call chain. 72 | 73 | We make some common use functions in promise mode, we call it SkinClass of a normal Class. And the API is almost same with official API. 74 | 75 | ### module 76 | 77 | origin: 78 | ```js 79 | var mongo = require('mongodb'); 80 | var Db = mongo.Db; 81 | var Server = mongo.Server; 82 | var MongoClient = mongo.MongoClient; 83 | var ReplSetServers = mongo.ReplSetServers; 84 | ... 85 | ``` 86 | 87 | mongoskin: 88 | 89 | ```js 90 | var mongo = require('mongoskin'); 91 | var Db = mongo.Db; 92 | var Server = mongo.Server; 93 | var MongoClient = mongo.MongoClient; 94 | var ReplSetServers = mongo.ReplSetServers; 95 | ... 96 | ``` 97 | 98 | ### MongoClient.connect(...) 99 | 100 | returns a `Db` instance 101 | 102 | alias origin `MongoClient.connect(..., function(err, db) { .... })` 103 | 104 | origin: 105 | 106 | ```js 107 | MongoClient.connect(..., function(err, db) { 108 | }) 109 | ``` 110 | 111 | mongoskin: 112 | 113 | ```js 114 | var db = MongoClient.connect(...) 115 | ``` 116 | 117 | ### db.collection(..., [callback]) 118 | 119 | returns a `Collection` instance 120 | 121 | alias origin `db.collection(..., function(err, collection) {....})` 122 | 123 | origin: 124 | 125 | ```js 126 | var db = new Db(...); 127 | db.open(function(err, db) { 128 | db.collection('myCollection', {strict: true}, function(err, myCollection) { 129 | // myCollection.find() ... 130 | }); 131 | }); 132 | ``` 133 | 134 | mongoskin: 135 | 136 | ```js 137 | var db = new Db(...); 138 | var myCollection = db.collection('myCollection', {strict: true}); 139 | ``` 140 | 141 | ## MongoSkin API part 142 | 143 | ### module.db(...) 144 | alias `MongoClient.connect(...)` 145 | ### module.helper.toObjectID(hexStr) 146 | convert `String` to `ObjectID` instance. 147 | ### db.bind(name, options) 148 | alias `db[name] = db.collection(name, options)` 149 | 150 | ```js 151 | db.bind('article') 152 | db.article.find().toArray(function(err, items) { 153 | assert.ok(err == null); 154 | }); 155 | ``` 156 | 157 | ### db.admin(...) 158 | alias `new Admin(db, ...)` 159 | ### db.grid(...) 160 | alias `new Grid(db, ...)` 161 | ### db.gridStore(...) 162 | alias `new GridStore(db, ...)` 163 | ### collection.bind(extendObject) 164 | each method of extendObject will be bind to collection. 165 | ### collection.findById(id, ...) 166 | alias `collection.find({_id: toObjectID(id)}, ...)` 167 | ### collection.updateById(id, ...) 168 | alias `collection.update({_id: toObjectID(id)}, ...)` 169 | ### collection.removeById(id, ...) 170 | alias `collection.remove({_id: toObjectID(id)}, ...)` 171 | 172 | ## NOTE!! mongoskin API change from 1.3.20 173 | 174 | Since node-mongodb-native has change a lot of API, mongoskin redesign from 1.3.20. The version number keep same with node-mongodb-native. And the API appearence is also keep same with node-mongodb-native 175 | 176 | ### Removed API from mongoskin 1.3.20 177 | 178 | * module.bind 179 | * module.Skin* 180 | * module.router 181 | * skinDb.toId 182 | * skinDb.toObjectId 183 | * skinDb.gridfs 184 | * skinCollection.bind 185 | 186 | ### Modified API from mongoskin 1.3.20 187 | 188 | * module.db 189 | * skinDb.bind 190 | 191 | 192 | ### Additional API from mongoskin 1.3.20 193 | 194 | * module.MongoClient 195 | * module.Grid 196 | * module.GridStore 197 | * module.helper.toObjectID 198 | 199 | ## Authors 200 | 201 | Below is the output from `git-summary`. 202 | 203 | ``` 204 | project : node-mongoskin 205 | repo age : 2 years, 10 months 206 | active : 84 days 207 | commits : 180 208 | files : 44 209 | authors : 210 | 49 Lin Gui 27.2% 211 | 44 fengmk2 24.4% 212 | 34 guilin 桂林 18.9% 213 | 23 Gui Lin 12.8% 214 | 5 guilin 2.8% 215 | 2 Raghu Katti 1.1% 216 | 2 Merlyn Albery-Speyer 1.1% 217 | 2 Paul Gebheim 1.1% 218 | 2 Joakim B 1.1% 219 | 2 François de Metz 1.1% 220 | 1 Wout Mertens 0.6% 221 | 1 Yuriy Nemtsov 0.6% 222 | 1 fresheneesz 0.6% 223 | 1 humanchimp 0.6% 224 | 1 Alan Shaw 0.6% 225 | 1 wmertens 0.6% 226 | 1 Aneil Mallavarapu 0.6% 227 | 1 Gustav 0.6% 228 | 1 Harvey McQueen 0.6% 229 | 1 Joe Faber 0.6% 230 | 1 Matt Perpick 0.6% 231 | 1 Philmod 0.6% 232 | 1 Quang Van 0.6% 233 | 1 Rakshit Menpara 0.6% 234 | 1 Shawn Jonnet 0.6% 235 | ``` 236 | 237 | ## License 238 | 239 | (The MIT License) 240 | 241 | Copyright (c) 2011 - 2012 kissjs.org 242 | 243 | Permission is hereby granted, free of charge, to any person obtaining 244 | a copy of this software and associated documentation files (the 245 | 'Software'), to deal in the Software without restriction, including 246 | without limitation the rights to use, copy, modify, merge, publish, 247 | distribute, sublicense, and/or sell copies of the Software, and to 248 | permit persons to whom the Software is furnished to do so, subject to 249 | the following conditions: 250 | 251 | The above copyright notice and this permission notice shall be 252 | included in all copies or substantial portions of the Software. 253 | 254 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 255 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 256 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 257 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 258 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 259 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 260 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 261 | -------------------------------------------------------------------------------- /test/collection.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * mongoskin - test/collection.js 3 | * 4 | * Copyright(c) 2011 - 2012 kissjs.org 5 | * Copyright(c) 2012 fengmk2 6 | * MIT Licensed 7 | */ 8 | 9 | "use strict"; 10 | 11 | /** 12 | * Module dependencies. 13 | */ 14 | 15 | var mongoskin = require('../'); 16 | var mongodb = require('mongodb'); 17 | var ObjectID = mongodb.ObjectID; 18 | var Collection = mongodb.Collection; 19 | var SkinCollection = mongoskin.SkinCollection; 20 | var Cursor = mongodb.Cursor; 21 | var should = require('should'); 22 | var servermanager = require('./utils/server_manager'); 23 | 24 | 25 | exports.testWithDb = function(db) { 26 | 27 | describe('collection.js', function () { 28 | 29 | var testcollection, commentcollection; 30 | before(function (done) { 31 | testcollection = db.collection('test_collection'); 32 | commentcollection = db.collection('comment'); 33 | 34 | testcollection.ensureIndex({title: -1}, function (err, index) { 35 | should.not.exist(err); 36 | index.should.equal('title_-1'); 37 | testcollection.findItems(function (err, rows) { 38 | should.not.exist(err); 39 | rows.should.be.instanceof(Array).with.length(0); 40 | done(); 41 | }); 42 | }); 43 | }); 44 | 45 | after(function (done) { 46 | testcollection.drop(function (err, result) { 47 | should.ok(result); 48 | done(err); 49 | }); 50 | }); 51 | 52 | it('should retrive native cursor', function(done) { 53 | db.collection('test_collection').find(function(err, cursor) { 54 | should.not.exists(err); 55 | cursor.toArray.should.be.instanceof(Function); 56 | should.not.exists(cursor.open); 57 | done(); 58 | }); 59 | }) 60 | 61 | describe('find(), findItems(), findEach()', function () { 62 | var objectIds = [], stringIds = []; 63 | before(function (done) { 64 | var inserts = []; 65 | for (var i = 0; i < 100; i++) { 66 | inserts.push({ 67 | text: 'this is comment ' + i, 68 | createtime: new Date() 69 | }); 70 | } 71 | commentcollection.insert(inserts, function (err, docs) { 72 | if (err) { 73 | return done(err); 74 | } 75 | for (var i = 0, l = docs.length; i < l; i++) { 76 | var doc = docs[i]; 77 | stringIds.push(doc._id.toString()); 78 | objectIds.push(doc._id); 79 | } 80 | done(); 81 | }); 82 | }); 83 | after(function (done) { 84 | commentcollection.drop(done); 85 | }); 86 | 87 | it('should find().toArray() return 100 comments', function (done) { 88 | commentcollection.find().toArray(function (err, rows) { 89 | should.not.exist(err); 90 | rows.should.be.instanceof(Array).with.length(100); 91 | done(); 92 | }); 93 | }); 94 | 95 | it('should findItems(fn) all comments', function (done) { 96 | commentcollection.findItems(function (err, comments) { 97 | should.not.exist(err); 98 | should.exist(comments); 99 | comments.should.be.instanceof(Array).with.length(100); 100 | done(); 101 | }); 102 | }); 103 | 104 | it('should findItems({} fn) all comments', function (done) { 105 | commentcollection.findItems(function (err, comments) { 106 | should.not.exist(err); 107 | should.exist(comments); 108 | comments.should.be.instanceof(Array).with.length(100); 109 | done(); 110 | }); 111 | }); 112 | 113 | it('should findItems({limit: 10}) query wrong return top 0 comments', function (done) { 114 | commentcollection.findItems({limit: 10}, function (err, comments) { 115 | should.not.exist(err); 116 | comments.should.be.instanceof(Array).with.length(0); 117 | done(); 118 | }); 119 | }); 120 | 121 | it('should findItems({}, {limit: 10}) return top 10 comments', function (done) { 122 | commentcollection.findItems({}, {limit: 10}, function (err, comments) { 123 | should.not.exist(err); 124 | comments.should.be.instanceof(Array).with.length(10); 125 | done(); 126 | }); 127 | }); 128 | 129 | it('should findEach(fn) call fn 100 times', function (done) { 130 | var count = 0; 131 | commentcollection.findEach(function (err, comment) { 132 | should.not.exist(err); 133 | if (!comment) { 134 | count.should.equal(100); 135 | return done(); 136 | } 137 | count++; 138 | }); 139 | }); 140 | 141 | it('should findEach({}, {limit: 20}, fn) call fn 20 times', function (done) { 142 | var count = 0; 143 | commentcollection.findEach({}, {limit: 20}, function (err, comment) { 144 | should.not.exist(err); 145 | if (!comment) { 146 | count.should.equal(20); 147 | return done(); 148 | } 149 | count++; 150 | }); 151 | }); 152 | 153 | describe('mock find() error', function () { 154 | var _find; 155 | before(function () { 156 | _find = commentcollection.find; 157 | commentcollection.find = function () { 158 | var callback = arguments[arguments.length - 1]; 159 | process.nextTick(function () { 160 | callback(new Error('mock find() error')); 161 | }); 162 | }; 163 | }); 164 | after(function () { 165 | if (_find) { 166 | commentcollection.find = _find; 167 | } 168 | }); 169 | 170 | it('should findItems() error', function (done) { 171 | commentcollection.findItems(function (err, docs) { 172 | should.exist(err); 173 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 174 | should.not.exist(docs); 175 | done(); 176 | }); 177 | }); 178 | it('should findEach() error', function (done) { 179 | commentcollection.findEach(function (err, docs) { 180 | should.exist(err); 181 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 182 | should.not.exist(docs); 183 | done(); 184 | }); 185 | }); 186 | }); 187 | 188 | }); 189 | 190 | describe('findById(), updateById(), removeById()', function () { 191 | var now = new Date(); 192 | var articleId; 193 | before(function (done) { 194 | db.bind('article'); 195 | var doc = { title: 'test article title ' + now, created_at: now }; 196 | db.article.insert(doc, function (err, res) { 197 | articleId = res.insertedIds[0]; 198 | done(err); 199 | }); 200 | }); 201 | after(function (done) { 202 | db.article.drop(done); 203 | }); 204 | 205 | it('should bind functions', function(done) { 206 | db.article.bind({ 207 | get: function(id, callback) { 208 | this.findById(id, callback); 209 | } 210 | }); 211 | db.article.get(articleId, done) 212 | }); 213 | 214 | describe('findById()', function () { 215 | it('should find one object by ObjectID', function (done) { 216 | db.article.findById(articleId, function (err, article) { 217 | should.not.exist(err); 218 | should.exist(article); 219 | article.should.have.property('_id').with.instanceof(ObjectID); 220 | article.should.have.property('created_at').with.instanceof(Date); 221 | article.should.have.property('title').with.include(now.toString()); 222 | article.created_at.toString().should.equal(now.toString()); 223 | done(); 224 | }); 225 | }); 226 | it('should find one object by String id', function (done) { 227 | db.article.findById(articleId.toString(), function (err, article) { 228 | should.not.exist(err); 229 | should.exist(article); 230 | article.should.have.property('_id').with.instanceof(ObjectID); 231 | article.should.have.property('created_at').with.instanceof(Date); 232 | article.should.have.property('title').with.include(now.toString()); 233 | article.created_at.toString().should.equal(now.toString()); 234 | done(); 235 | }); 236 | }); 237 | it('should not find when id not exists', function (done) { 238 | db.article.findById('foo', function (err, article) { 239 | should.not.exist(err); 240 | should.not.exist(article); 241 | done(); 242 | }); 243 | }); 244 | }); 245 | 246 | describe('updateById()', function () { 247 | it('should update obj by id', function (done) { 248 | var updatedTime = new Date(); 249 | var doc = { 250 | $set: { 251 | title: 'new title ' + updatedTime, 252 | updated_at: updatedTime 253 | } 254 | }; 255 | db.article.updateById(articleId.toString(), doc, function (err, result) { 256 | should.not.exist(err); 257 | result.should.have.property('ok', 1); 258 | db.article.findById(articleId, function (err, article) { 259 | should.not.exist(err); 260 | should.exist(article); 261 | article.should.have.property('title', 'new title ' + updatedTime); 262 | article.should.have.property('updated_at').with.instanceof(Date); 263 | article.updated_at.toString().should.equal(updatedTime.toString()); 264 | done(); 265 | }); 266 | }); 267 | }); 268 | 269 | it('with no callback', function(done) { 270 | var updatedTime = new Date(); 271 | var doc = { 272 | $set: { 273 | title: 'new title ' + updatedTime, 274 | updated_at: updatedTime 275 | } 276 | }; 277 | db.article.updateById(articleId.toString(), doc); 278 | 279 | setTimeout(function() { 280 | done(); 281 | }, 0); 282 | }); 283 | }); 284 | 285 | describe('removeById()', function () { 286 | it('should remove obj by id', function (done) { 287 | var id = articleId.toString(); 288 | db.article.findById(id, function (err, article) { 289 | should.not.exist(err); 290 | should.exist(article); 291 | db.article.removeById(id, function (err, success) { 292 | should.not.exist(err); 293 | success.should.equal(1); 294 | db.article.findById(id, function (err, article) { 295 | should.not.exist(err); 296 | should.not.exist(article); 297 | done(); 298 | }); 299 | }); 300 | }); 301 | }); 302 | 303 | it('should remove not exists obj', function (done) { 304 | var id = articleId.toString(); 305 | db.article.removeById(id, function (err, res) { 306 | should.not.exist(err); 307 | res.should.equal(0); 308 | done(); 309 | }); 310 | }); 311 | 312 | it('no callback', function(done) { 313 | var id = articleId.toString(); 314 | db.article.removeById(id); 315 | setTimeout(function() { 316 | done(); 317 | }, 0); 318 | }); 319 | }); 320 | 321 | }); 322 | }); 323 | } 324 | -------------------------------------------------------------------------------- /test_results.md: -------------------------------------------------------------------------------- 1 | # TOC 2 | - [helper.id()](#helperid) 3 | - [connect_db](#connect_db) 4 | - [db.js](#connect_db-dbjs) 5 | - [collection.js](#connect_db-collectionjs) 6 | - [find(), findItems(), findEach()](#connect_db-collectionjs-find-finditems-findeach) 7 | - [mock find() error](#connect_db-collectionjs-find-finditems-findeach-mock-find-error) 8 | - [findById(), updateById(), removeById()](#connect_db-collectionjs-findbyid-updatebyid-removebyid) 9 | - [findById()](#connect_db-collectionjs-findbyid-updatebyid-removebyid-findbyid) 10 | - [updateById()](#connect_db-collectionjs-findbyid-updatebyid-removebyid-updatebyid) 11 | - [removeById()](#connect_db-collectionjs-findbyid-updatebyid-removebyid-removebyid) 12 | - [cursor.js](#connect_db-cursorjs) 13 | - [db.admin()](#connect_db-dbadmin) 14 | - [new Admin(db)](#connect_db-new-admindb) 15 | - [db.grid()](#connect_db-dbgrid) 16 | - [new Grid(db, fsName)](#connect_db-new-griddb-fsname) 17 | - [grid_store.js](#connect_db-grid_storejs) 18 | - [new_db](#new_db) 19 | - [db.js](#new_db-dbjs) 20 | - [collection.js](#new_db-collectionjs) 21 | - [find(), findItems(), findEach()](#new_db-collectionjs-find-finditems-findeach) 22 | - [mock find() error](#new_db-collectionjs-find-finditems-findeach-mock-find-error) 23 | - [findById(), updateById(), removeById()](#new_db-collectionjs-findbyid-updatebyid-removebyid) 24 | - [findById()](#new_db-collectionjs-findbyid-updatebyid-removebyid-findbyid) 25 | - [updateById()](#new_db-collectionjs-findbyid-updatebyid-removebyid-updatebyid) 26 | - [removeById()](#new_db-collectionjs-findbyid-updatebyid-removebyid-removebyid) 27 | - [cursor.js](#new_db-cursorjs) 28 | - [db.admin()](#new_db-dbadmin) 29 | - [new Admin(db)](#new_db-new-admindb) 30 | - [db.grid()](#new_db-dbgrid) 31 | - [new Grid(db, fsName)](#new_db-new-griddb-fsname) 32 | - [grid_store.js](#new_db-grid_storejs) 33 | - [makeSkinClass](#makeskinclass) 34 | - [SkinClass](#makeskinclass-skinclass) 35 | 36 | 37 | 38 | # helper.id() 39 | should convert string id to ObjectID success. 40 | 41 | ```js 42 | var id = '4ec4b2b9f44a927223000001'; 43 | id = helper.toObjectID(id); 44 | id.should.be.instanceof(ObjectID); 45 | id = helper.toObjectID(id); 46 | id.should.be.instanceof(ObjectID); 47 | id = '4ec4b2b9f44a927223000foo'; 48 | id = helper.toObjectID(id); 49 | id.should.be.instanceof(ObjectID); 50 | ``` 51 | 52 | should return source id when id length !== 24. 53 | 54 | ```js 55 | var ids = [123, '4ec4b2b9f44a92722300000', 'abc', '4ec4b2b9f44a927223000f00123123']; 56 | ids.forEach(function (id) { 57 | helper.toObjectID(id).should.equal(id); 58 | }); 59 | ``` 60 | 61 | 62 | # connect_db 63 | 64 | ## db.js 65 | skinDb.collection() should retrive native collection with callback. 66 | 67 | ```js 68 | var skinColl = db.collection('testRetriveCollection', function(err, coll) { 69 | should.not.exist(err); 70 | skinColl._native.should.eql(coll); 71 | done(); 72 | }); 73 | should.exist(skinColl); 74 | ``` 75 | 76 | 77 | ## collection.js 78 | should retrive native cursor. 79 | 80 | ```js 81 | db.collection('test_collection').find(function(err, cursor) { 82 | should.not.exists(err); 83 | cursor.toArray.should.be.instanceof(Function); 84 | should.not.exists(cursor.open); 85 | done(); 86 | }); 87 | ``` 88 | 89 | 90 | ### find(), findItems(), findEach() 91 | should find().toArray() return 100 comments. 92 | 93 | ```js 94 | commentcollection.find().toArray(function (err, rows) { 95 | should.not.exist(err); 96 | rows.should.be.instanceof(Array).with.length(100); 97 | done(); 98 | }); 99 | ``` 100 | 101 | should findItems(fn) all comments. 102 | 103 | ```js 104 | commentcollection.findItems(function (err, comments) { 105 | should.not.exist(err); 106 | should.exist(comments); 107 | comments.should.be.instanceof(Array).with.length(100); 108 | done(); 109 | }); 110 | ``` 111 | 112 | should findItems({} fn) all comments. 113 | 114 | ```js 115 | commentcollection.findItems(function (err, comments) { 116 | should.not.exist(err); 117 | should.exist(comments); 118 | comments.should.be.instanceof(Array).with.length(100); 119 | done(); 120 | }); 121 | ``` 122 | 123 | should findItems({limit: 10}) query wrong return top 0 comments. 124 | 125 | ```js 126 | commentcollection.findItems({limit: 10}, function (err, comments) { 127 | should.not.exist(err); 128 | comments.should.be.instanceof(Array).with.length(0); 129 | done(); 130 | }); 131 | ``` 132 | 133 | should findItems({}, {limit: 10}) return top 10 comments. 134 | 135 | ```js 136 | commentcollection.findItems({}, {limit: 10}, function (err, comments) { 137 | should.not.exist(err); 138 | comments.should.be.instanceof(Array).with.length(10); 139 | done(); 140 | }); 141 | ``` 142 | 143 | should findEach(fn) call fn 100 times. 144 | 145 | ```js 146 | var count = 0; 147 | commentcollection.findEach(function (err, comment) { 148 | should.not.exist(err); 149 | if (!comment) { 150 | count.should.equal(100); 151 | return done(); 152 | } 153 | count++; 154 | }); 155 | ``` 156 | 157 | should findEach({}, {limit: 20}, fn) call fn 20 times. 158 | 159 | ```js 160 | var count = 0; 161 | commentcollection.findEach({}, {limit: 20}, function (err, comment) { 162 | should.not.exist(err); 163 | if (!comment) { 164 | count.should.equal(20); 165 | return done(); 166 | } 167 | count++; 168 | }); 169 | ``` 170 | 171 | 172 | #### mock find() error 173 | should findItems() error. 174 | 175 | ```js 176 | commentcollection.findItems(function (err, docs) { 177 | should.exist(err); 178 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 179 | should.not.exist(docs); 180 | done(); 181 | }); 182 | ``` 183 | 184 | should findEach() error. 185 | 186 | ```js 187 | commentcollection.findEach(function (err, docs) { 188 | should.exist(err); 189 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 190 | should.not.exist(docs); 191 | done(); 192 | }); 193 | ``` 194 | 195 | 196 | ### findById(), updateById(), removeById() 197 | 198 | #### findById() 199 | should find one object by ObjectID. 200 | 201 | ```js 202 | db.article.findById(articleId, function (err, article) { 203 | should.not.exist(err); 204 | should.exist(article); 205 | article.should.have.property('_id').with.instanceof(ObjectID); 206 | article.should.have.property('created_at').with.instanceof(Date); 207 | article.should.have.property('title').with.include(now.toString()); 208 | article.created_at.toString().should.equal(now.toString()); 209 | done(); 210 | }); 211 | ``` 212 | 213 | should find one object by String id. 214 | 215 | ```js 216 | db.article.findById(articleId.toString(), function (err, article) { 217 | should.not.exist(err); 218 | should.exist(article); 219 | article.should.have.property('_id').with.instanceof(ObjectID); 220 | article.should.have.property('created_at').with.instanceof(Date); 221 | article.should.have.property('title').with.include(now.toString()); 222 | article.created_at.toString().should.equal(now.toString()); 223 | done(); 224 | }); 225 | ``` 226 | 227 | should not find when id not exists. 228 | 229 | ```js 230 | db.article.findById('foo', function (err, article) { 231 | should.not.exist(err); 232 | should.not.exist(article); 233 | done(); 234 | }); 235 | ``` 236 | 237 | 238 | #### updateById() 239 | should update obj by id. 240 | 241 | ```js 242 | var updatedTime = new Date(); 243 | var doc = { 244 | $set: { 245 | title: 'new title ' + updatedTime, 246 | updated_at: updatedTime 247 | } 248 | }; 249 | db.article.updateById(articleId.toString(), doc, function (err, success, result) { 250 | should.not.exist(err); 251 | success.should.equal(1); 252 | result.should.have.property('ok', 1); 253 | db.article.findById(articleId, function (err, article) { 254 | should.not.exist(err); 255 | should.exist(article); 256 | article.should.have.property('title', 'new title ' + updatedTime); 257 | article.should.have.property('updated_at').with.instanceof(Date); 258 | article.updated_at.toString().should.equal(updatedTime.toString()); 259 | done(); 260 | }); 261 | }); 262 | ``` 263 | 264 | 265 | #### removeById() 266 | should remove obj by id. 267 | 268 | ```js 269 | var id = articleId.toString(); 270 | db.article.findById(id, function (err, article) { 271 | should.not.exist(err); 272 | should.exist(article); 273 | db.article.removeById(id, function (err, success) { 274 | should.not.exist(err); 275 | success.should.equal(1); 276 | db.article.findById(id, function (err, article) { 277 | should.not.exist(err); 278 | should.not.exist(article); 279 | done(); 280 | }); 281 | }); 282 | }); 283 | ``` 284 | 285 | should remove not exists obj. 286 | 287 | ```js 288 | var id = articleId.toString(); 289 | db.article.removeById(id, function (err, success) { 290 | should.not.exist(err); 291 | success.should.equal(0); 292 | done(); 293 | }); 294 | ``` 295 | 296 | 297 | ## cursor.js 298 | should call toArray(). 299 | 300 | ```js 301 | db.collection('testCursor').find().toArray(function(err, items) { 302 | should.not.exist(err); 303 | items.should.be.instanceof(Array).with.length(100); 304 | done(); 305 | }); 306 | ``` 307 | 308 | should cursor.skip(10).limit(10).toArray() return 10 rows. 309 | 310 | ```js 311 | db.collection('testCursor').find().skip(10).limit(10).toArray(function (err, rows) { 312 | should.not.exist(err); 313 | should.exist(rows); 314 | rows.should.be.instanceof(Array).with.length(10); 315 | rows[0].name.should.equal('name 10'); 316 | rows[9].name.should.equal('name 19'); 317 | done(); 318 | }); 319 | ``` 320 | 321 | should cursor.sort({index: -1}).skip(20).limit(10).toArray() return 10 rows. 322 | 323 | ```js 324 | db.collection('testCursor').find().sort({index: -1}).skip(20).limit(10).toArray(function (err, rows) { 325 | should.not.exist(err); 326 | should.exist(rows); 327 | rows.should.be.instanceof(Array).with.length(10); 328 | rows[0].name.should.equal('name 79'); 329 | rows[9].name.should.equal('name 70'); 330 | done(); 331 | }); 332 | ``` 333 | 334 | should cursor.count() return 100. 335 | 336 | ```js 337 | db.collection('testCursor').find().count(function (err, count) { 338 | should.not.exist(err); 339 | count.should.equal(100); 340 | done(); 341 | }); 342 | ``` 343 | 344 | should cursor.explain() return 100. 345 | 346 | ```js 347 | db.collection('testCursor').find({index: {$gt: 50}}).explain(function (err, result) { 348 | should.not.exist(err); 349 | result.should.have.property('cursor', 'BasicCursor'); 350 | result.should.have.property('nscanned', 100); 351 | result.should.have.property('nscannedObjects', 100); 352 | result.should.have.property('n', 49); 353 | done(); 354 | }); 355 | ``` 356 | 357 | 358 | ## db.admin() 359 | should add the new user to the admin database. 360 | 361 | ```js 362 | adminDb.addUser('admin3', 'admin3', done); 363 | ``` 364 | 365 | should authenticate using the newly added user. 366 | 367 | ```js 368 | adminDb.authenticate('admin3', 'admin3', done); 369 | ``` 370 | 371 | should retrive the build information for the mongodb instance. 372 | 373 | ```js 374 | adminDb.buildInfo(done); 375 | ``` 376 | 377 | should remove user just added. 378 | 379 | ```js 380 | adminDb.removeUser('admin3', done); 381 | ``` 382 | 383 | 384 | ## new Admin(db) 385 | should add the new user to the admin database. 386 | 387 | ```js 388 | adminDb.addUser('admin3', 'admin3', done); 389 | ``` 390 | 391 | should authenticate using the newly added user. 392 | 393 | ```js 394 | adminDb.authenticate('admin3', 'admin3', done); 395 | ``` 396 | 397 | should retrive the build information for the mongodb instance. 398 | 399 | ```js 400 | adminDb.buildInfo(done); 401 | ``` 402 | 403 | should remove user just added. 404 | 405 | ```js 406 | adminDb.removeUser('admin3', done); 407 | ``` 408 | 409 | 410 | ## db.grid() 411 | should write data to grid. 412 | 413 | ```js 414 | grid.put(originalData, {}, function(err, result) { 415 | should.not.exist(err); 416 | result._id.should.not.eql(id); 417 | done(); 418 | }); 419 | ``` 420 | 421 | should get data just put to grid. 422 | 423 | ```js 424 | grid.get(id, function(err, data) { 425 | assert.deepEqual(originalData.toString('base64'), data.toString('base64')); 426 | done(err); 427 | }); 428 | ``` 429 | 430 | 431 | ## new Grid(db, fsName) 432 | should write data to grid. 433 | 434 | ```js 435 | grid.put(originalData, {}, function(err, result) { 436 | should.not.exist(err); 437 | result._id.should.not.eql(id); 438 | done(); 439 | }); 440 | ``` 441 | 442 | should get data just put to grid. 443 | 444 | ```js 445 | grid.get(id, function(err, data) { 446 | assert.deepEqual(originalData.toString('base64'), data.toString('base64')); 447 | done(err); 448 | }); 449 | ``` 450 | 451 | 452 | ## grid_store.js 453 | should write data to file. 454 | 455 | ```js 456 | // Write a text string 457 | gridStore.write(originData, function(err) { 458 | gridStore.close(done); 459 | }); 460 | ``` 461 | 462 | should read file. 463 | 464 | ```js 465 | // use mongoskin style to create gridStore 466 | db.gridStore(fileId, 'r').read(function(err, data) { 467 | should.not.exist(err); 468 | data.toString().should.equal(originData); 469 | done(); 470 | }) 471 | ``` 472 | 473 | should execute GridStore static methods. 474 | 475 | ```js 476 | GridStore.exist(db, fileId, done) 477 | ``` 478 | 479 | 480 | # new_db 481 | 482 | ## db.js 483 | skinDb.collection() should retrive native collection with callback. 484 | 485 | ```js 486 | var skinColl = db.collection('testRetriveCollection', function(err, coll) { 487 | should.not.exist(err); 488 | skinColl._native.should.eql(coll); 489 | done(); 490 | }); 491 | should.exist(skinColl); 492 | ``` 493 | 494 | 495 | ## collection.js 496 | should retrive native cursor. 497 | 498 | ```js 499 | db.collection('test_collection').find(function(err, cursor) { 500 | should.not.exists(err); 501 | cursor.toArray.should.be.instanceof(Function); 502 | should.not.exists(cursor.open); 503 | done(); 504 | }); 505 | ``` 506 | 507 | 508 | ### find(), findItems(), findEach() 509 | should find().toArray() return 100 comments. 510 | 511 | ```js 512 | commentcollection.find().toArray(function (err, rows) { 513 | should.not.exist(err); 514 | rows.should.be.instanceof(Array).with.length(100); 515 | done(); 516 | }); 517 | ``` 518 | 519 | should findItems(fn) all comments. 520 | 521 | ```js 522 | commentcollection.findItems(function (err, comments) { 523 | should.not.exist(err); 524 | should.exist(comments); 525 | comments.should.be.instanceof(Array).with.length(100); 526 | done(); 527 | }); 528 | ``` 529 | 530 | should findItems({} fn) all comments. 531 | 532 | ```js 533 | commentcollection.findItems(function (err, comments) { 534 | should.not.exist(err); 535 | should.exist(comments); 536 | comments.should.be.instanceof(Array).with.length(100); 537 | done(); 538 | }); 539 | ``` 540 | 541 | should findItems({limit: 10}) query wrong return top 0 comments. 542 | 543 | ```js 544 | commentcollection.findItems({limit: 10}, function (err, comments) { 545 | should.not.exist(err); 546 | comments.should.be.instanceof(Array).with.length(0); 547 | done(); 548 | }); 549 | ``` 550 | 551 | should findItems({}, {limit: 10}) return top 10 comments. 552 | 553 | ```js 554 | commentcollection.findItems({}, {limit: 10}, function (err, comments) { 555 | should.not.exist(err); 556 | comments.should.be.instanceof(Array).with.length(10); 557 | done(); 558 | }); 559 | ``` 560 | 561 | should findEach(fn) call fn 100 times. 562 | 563 | ```js 564 | var count = 0; 565 | commentcollection.findEach(function (err, comment) { 566 | should.not.exist(err); 567 | if (!comment) { 568 | count.should.equal(100); 569 | return done(); 570 | } 571 | count++; 572 | }); 573 | ``` 574 | 575 | should findEach({}, {limit: 20}, fn) call fn 20 times. 576 | 577 | ```js 578 | var count = 0; 579 | commentcollection.findEach({}, {limit: 20}, function (err, comment) { 580 | should.not.exist(err); 581 | if (!comment) { 582 | count.should.equal(20); 583 | return done(); 584 | } 585 | count++; 586 | }); 587 | ``` 588 | 589 | 590 | #### mock find() error 591 | should findItems() error. 592 | 593 | ```js 594 | commentcollection.findItems(function (err, docs) { 595 | should.exist(err); 596 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 597 | should.not.exist(docs); 598 | done(); 599 | }); 600 | ``` 601 | 602 | should findEach() error. 603 | 604 | ```js 605 | commentcollection.findEach(function (err, docs) { 606 | should.exist(err); 607 | err.should.be.instanceof(Error).with.have.property('message', 'mock find() error'); 608 | should.not.exist(docs); 609 | done(); 610 | }); 611 | ``` 612 | 613 | 614 | ### findById(), updateById(), removeById() 615 | 616 | #### findById() 617 | should find one object by ObjectID. 618 | 619 | ```js 620 | db.article.findById(articleId, function (err, article) { 621 | should.not.exist(err); 622 | should.exist(article); 623 | article.should.have.property('_id').with.instanceof(ObjectID); 624 | article.should.have.property('created_at').with.instanceof(Date); 625 | article.should.have.property('title').with.include(now.toString()); 626 | article.created_at.toString().should.equal(now.toString()); 627 | done(); 628 | }); 629 | ``` 630 | 631 | should find one object by String id. 632 | 633 | ```js 634 | db.article.findById(articleId.toString(), function (err, article) { 635 | should.not.exist(err); 636 | should.exist(article); 637 | article.should.have.property('_id').with.instanceof(ObjectID); 638 | article.should.have.property('created_at').with.instanceof(Date); 639 | article.should.have.property('title').with.include(now.toString()); 640 | article.created_at.toString().should.equal(now.toString()); 641 | done(); 642 | }); 643 | ``` 644 | 645 | should not find when id not exists. 646 | 647 | ```js 648 | db.article.findById('foo', function (err, article) { 649 | should.not.exist(err); 650 | should.not.exist(article); 651 | done(); 652 | }); 653 | ``` 654 | 655 | 656 | #### updateById() 657 | should update obj by id. 658 | 659 | ```js 660 | var updatedTime = new Date(); 661 | var doc = { 662 | $set: { 663 | title: 'new title ' + updatedTime, 664 | updated_at: updatedTime 665 | } 666 | }; 667 | db.article.updateById(articleId.toString(), doc, function (err, success, result) { 668 | should.not.exist(err); 669 | success.should.equal(1); 670 | result.should.have.property('ok', 1); 671 | db.article.findById(articleId, function (err, article) { 672 | should.not.exist(err); 673 | should.exist(article); 674 | article.should.have.property('title', 'new title ' + updatedTime); 675 | article.should.have.property('updated_at').with.instanceof(Date); 676 | article.updated_at.toString().should.equal(updatedTime.toString()); 677 | done(); 678 | }); 679 | }); 680 | ``` 681 | 682 | 683 | #### removeById() 684 | should remove obj by id. 685 | 686 | ```js 687 | var id = articleId.toString(); 688 | db.article.findById(id, function (err, article) { 689 | should.not.exist(err); 690 | should.exist(article); 691 | db.article.removeById(id, function (err, success) { 692 | should.not.exist(err); 693 | success.should.equal(1); 694 | db.article.findById(id, function (err, article) { 695 | should.not.exist(err); 696 | should.not.exist(article); 697 | done(); 698 | }); 699 | }); 700 | }); 701 | ``` 702 | 703 | should remove not exists obj. 704 | 705 | ```js 706 | var id = articleId.toString(); 707 | db.article.removeById(id, function (err, success) { 708 | should.not.exist(err); 709 | success.should.equal(0); 710 | done(); 711 | }); 712 | ``` 713 | 714 | 715 | ## cursor.js 716 | should call toArray(). 717 | 718 | ```js 719 | db.collection('testCursor').find().toArray(function(err, items) { 720 | should.not.exist(err); 721 | items.should.be.instanceof(Array).with.length(100); 722 | done(); 723 | }); 724 | ``` 725 | 726 | should cursor.skip(10).limit(10).toArray() return 10 rows. 727 | 728 | ```js 729 | db.collection('testCursor').find().skip(10).limit(10).toArray(function (err, rows) { 730 | should.not.exist(err); 731 | should.exist(rows); 732 | rows.should.be.instanceof(Array).with.length(10); 733 | rows[0].name.should.equal('name 10'); 734 | rows[9].name.should.equal('name 19'); 735 | done(); 736 | }); 737 | ``` 738 | 739 | should cursor.sort({index: -1}).skip(20).limit(10).toArray() return 10 rows. 740 | 741 | ```js 742 | db.collection('testCursor').find().sort({index: -1}).skip(20).limit(10).toArray(function (err, rows) { 743 | should.not.exist(err); 744 | should.exist(rows); 745 | rows.should.be.instanceof(Array).with.length(10); 746 | rows[0].name.should.equal('name 79'); 747 | rows[9].name.should.equal('name 70'); 748 | done(); 749 | }); 750 | ``` 751 | 752 | should cursor.count() return 100. 753 | 754 | ```js 755 | db.collection('testCursor').find().count(function (err, count) { 756 | should.not.exist(err); 757 | count.should.equal(100); 758 | done(); 759 | }); 760 | ``` 761 | 762 | should cursor.explain() return 100. 763 | 764 | ```js 765 | db.collection('testCursor').find({index: {$gt: 50}}).explain(function (err, result) { 766 | should.not.exist(err); 767 | result.should.have.property('cursor', 'BasicCursor'); 768 | result.should.have.property('nscanned', 100); 769 | result.should.have.property('nscannedObjects', 100); 770 | result.should.have.property('n', 49); 771 | done(); 772 | }); 773 | ``` 774 | 775 | 776 | ## db.admin() 777 | should add the new user to the admin database. 778 | 779 | ```js 780 | adminDb.addUser('admin3', 'admin3', done); 781 | ``` 782 | 783 | should authenticate using the newly added user. 784 | 785 | ```js 786 | adminDb.authenticate('admin3', 'admin3', done); 787 | ``` 788 | 789 | should retrive the build information for the mongodb instance. 790 | 791 | ```js 792 | adminDb.buildInfo(done); 793 | ``` 794 | 795 | should remove user just added. 796 | 797 | ```js 798 | adminDb.removeUser('admin3', done); 799 | ``` 800 | 801 | 802 | ## new Admin(db) 803 | should add the new user to the admin database. 804 | 805 | ```js 806 | adminDb.addUser('admin3', 'admin3', done); 807 | ``` 808 | 809 | should authenticate using the newly added user. 810 | 811 | ```js 812 | adminDb.authenticate('admin3', 'admin3', done); 813 | ``` 814 | 815 | should retrive the build information for the mongodb instance. 816 | 817 | ```js 818 | adminDb.buildInfo(done); 819 | ``` 820 | 821 | should remove user just added. 822 | 823 | ```js 824 | adminDb.removeUser('admin3', done); 825 | ``` 826 | 827 | 828 | ## db.grid() 829 | should write data to grid. 830 | 831 | ```js 832 | grid.put(originalData, {}, function(err, result) { 833 | should.not.exist(err); 834 | result._id.should.not.eql(id); 835 | done(); 836 | }); 837 | ``` 838 | 839 | should get data just put to grid. 840 | 841 | ```js 842 | grid.get(id, function(err, data) { 843 | assert.deepEqual(originalData.toString('base64'), data.toString('base64')); 844 | done(err); 845 | }); 846 | ``` 847 | 848 | 849 | ## new Grid(db, fsName) 850 | should write data to grid. 851 | 852 | ```js 853 | grid.put(originalData, {}, function(err, result) { 854 | should.not.exist(err); 855 | result._id.should.not.eql(id); 856 | done(); 857 | }); 858 | ``` 859 | 860 | should get data just put to grid. 861 | 862 | ```js 863 | grid.get(id, function(err, data) { 864 | assert.deepEqual(originalData.toString('base64'), data.toString('base64')); 865 | done(err); 866 | }); 867 | ``` 868 | 869 | 870 | ## grid_store.js 871 | should write data to file. 872 | 873 | ```js 874 | // Write a text string 875 | gridStore.write(originData, function(err) { 876 | gridStore.close(done); 877 | }); 878 | ``` 879 | 880 | should read file. 881 | 882 | ```js 883 | // use mongoskin style to create gridStore 884 | db.gridStore(fileId, 'r').read(function(err, data) { 885 | should.not.exist(err); 886 | data.toString().should.equal(originData); 887 | done(); 888 | }) 889 | ``` 890 | 891 | should execute GridStore static methods. 892 | 893 | ```js 894 | GridStore.exist(db, fileId, done) 895 | ``` 896 | 897 | 898 | # makeSkinClass 899 | 900 | ## SkinClass 901 | should call native method. 902 | 903 | ```js 904 | skinFoo.get('echo', function(err, echo) { 905 | should.not.exists(err); 906 | echo.should.eql('echo'); 907 | done(); 908 | }); 909 | ``` 910 | 911 | should callback error if error occused. 912 | 913 | ```js 914 | skinFoo.makeError('123', function(err) { 915 | err.code.should.eql('123'); 916 | done(); 917 | }) 918 | ``` 919 | 920 | should chain operations. 921 | 922 | ```js 923 | skinFoo.chain().chain().chain().get('echo', done); 924 | ``` 925 | 926 | should log open error if no callback. 927 | 928 | ```js 929 | var errFoo = new SkinFoo(); 930 | errFoo.willOpenError = true; 931 | errFoo.chain(); 932 | setTimeout(done, 15); 933 | ``` 934 | 935 | should callback open error in chain callback. 936 | 937 | ```js 938 | var errFoo = new SkinFoo(); 939 | errFoo.willOpenError = true; 940 | errFoo.chain().chain().chain().get(function(err) { 941 | err.code.should.eql('ERROPEN'); 942 | done(); 943 | }); 944 | ``` 945 | 946 | should get native property after open. 947 | 948 | ```js 949 | skinFoo.isOpen.should.be.true; 950 | done(); 951 | ``` 952 | 953 | should set native property before open. 954 | 955 | ```js 956 | var foo = new SkinFoo(); 957 | foo.isOpen = 'abc'; 958 | foo.open(function(err, p_foo) { 959 | should.not.exists(err); 960 | p_foo.isOpen.should.eql('abc'); 961 | done(); 962 | }) 963 | ``` 964 | 965 | should close just while openning. 966 | 967 | ```js 968 | var foo = new SkinFoo(); 969 | foo.chain().close(done); 970 | ``` 971 | 972 | should call close even closing or closed. 973 | 974 | ```js 975 | var foo = new SkinFoo(); 976 | foo.chain().close().close(done); 977 | ``` 978 | 979 | --------------------------------------------------------------------------------