diff --git a/.travis.yml b/.travis.yml index f897cb1..055a750 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: node_js node_js: - - "4.2.4" + - "4.2" + - "stable" services: - mongodb diff --git a/LICENSE b/LICENSE index 7098dbd..2de9244 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2011-2015, Edward Hotchkiss & Nick Baugh +Copyright (c) 2011-2016, Edward Hotchkiss, Nick Baugh & Dmitry Kirilyuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/index.js b/index.js index 8af68dd..f4e5bfe 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,7 @@ 'use strict'; +const mongoose = require('mongoose'); + /** * @package mongoose-paginate * @param {Object} [query={}] @@ -23,9 +25,10 @@ function paginate(query, options, callback) { let sort = options.sort; let populate = options.populate; let lean = options.lean || false; - let leanWithId = options.leanWithId ? options.leanWithId : true; - let limit = options.limit ? options.limit : 10; - let page, offset, skip, promises; + let leanWithId = options.hasOwnProperty('leanWithId') ? options.leanWithId : true; + let limit = options.hasOwnProperty('limit') ? options.limit : 10; + let page, offset, skip, docsQuery, promises; + if (options.offset) { offset = options.offset; skip = offset; @@ -37,58 +40,69 @@ function paginate(query, options, callback) { offset = 0; skip = offset; } - if (limit) { - let docsQuery = this.find(query) + + if (limit > 0) { + docsQuery = this.find(query) .select(select) .sort(sort) .skip(skip) .limit(limit) .lean(lean); + if (populate) { - [].concat(populate).forEach((item) => { - docsQuery.populate(item); - }); + [].concat(populate).forEach((item) => docsQuery.populate(item)); } - promises = { - docs: docsQuery.exec(), - count: this.count(query).exec() - }; - if (lean && leanWithId) { - promises.docs = promises.docs.then((docs) => { - docs.forEach((doc) => { + } + + promises = [ + docsQuery ? docsQuery.exec() : Promise.resolve({}), + this.count(query).exec() + ]; + + let promise = new Promise((resolve, reject) => { + Promise.all(promises).then((data) => { + let docs = (limit > 0) ? data[0] : []; + let count = data[1]; + let result = { + docs: docs, + total: count, + limit: limit + }; + if (lean && leanWithId) { + result.docs = result.docs.map((doc) => { doc.id = String(doc._id); + return doc; }); - return docs; - }); - } - } - promises = Object.keys(promises).map((x) => promises[x]); - return Promise.all(promises).then((data) => { - let result = { - docs: data.docs, - total: data.count, - limit: limit - }; - if (offset !== undefined) { - result.offset = offset; - } - if (page !== undefined) { - result.page = page; - result.pages = Math.ceil(data.count / limit) || 1; - } - if (typeof callback === 'function') { - return callback(null, result); - } - let promise = new Promise(); - promise.resolve(result); - return promise; + } + if (offset !== undefined) { + result.offset = offset; + } + if (page !== undefined) { + result.page = page; + result.pages = Math.ceil(result.total / limit) || 1; + } + if (typeof callback === 'function') { + return callback(null, result); + } + resolve(result); + }, (error) => { + if (typeof callback === 'function') { + return callback(error, null); + } + reject(error); + }); }); + + return promise; } /** * @param {Schema} schema + * use native ES6 promises verus mpromise */ +mongoose.Promise = global.Promise; + module.exports = function(schema) { schema.statics.paginate = paginate; }; diff --git a/package.json b/package.json index 2f9149d..505ba38 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose-paginate", "description": "Pagination plugin for Mongoose", - "version": "5.0.0", + "version": "6.0.0", "author": { "name": "Edward Hotchkiss", "email": "edward@edwardhotchkiss.com" @@ -33,13 +33,13 @@ "page" ], "engines": { - "node": ">=4.2.4" + "node": ">=4.2" }, "dependencies": {}, "devDependencies": { - "mongoose": "4.3.4", - "mocha": "2.3.4", - "chai": "3.4.1" + "mongoose": ">=4.2", + "mocha": "~2.3.4", + "chai": "~3.4.1" }, "scripts": { "test": "./node_modules/.bin/mocha tests/*.js -R spec --ui bdd --timeout 5000" diff --git a/tests/index.js b/tests/index.js index 7a1a8d2..13331af 100644 --- a/tests/index.js +++ b/tests/index.js @@ -19,23 +19,22 @@ let BookSchema = new mongoose.Schema({ }); BookSchema.plugin(mongoosePaginate); - let Book = mongoose.model('Book', BookSchema); -describe('mongoose-paginate', function() { +describe('mongoose-paginate', () => { - before(function(done) { + before((done) => { mongoose.connect(MONGO_URI, done); }); - before(function(done) { + before((done) => { mongoose.connection.db.dropDatabase(done); }); - before(function() { + before(() => { let book, books = []; let date = new Date(); - return Author.create({ name: 'Arthur Conan Doyle' }).then(function(author) { + return Author.create({ name: 'Arthur Conan Doyle' }).then((author) => { for (let i = 1; i <= 100; i++) { book = new Book({ title: 'Book #' + i, @@ -48,76 +47,82 @@ describe('mongoose-paginate', function() { }); }); - afterEach(function() { - delete mongoosePaginate.paginate.options; - }); - - it('returns promise', function() { + it('returns promise', () => { let promise = Book.paginate(); expect(promise.then).to.be.an.instanceof(Function); }); - it('calls callback', function(done) { - Book.paginate({}, {}, function(err, result) { - expect(err).to.be.null; + it('calls callback', (done) => { + Book.paginate({}, {}, (error, result) => { + expect(error).to.be.null; expect(result).to.be.an.instanceOf(Object); done(); + }, (error) => { + expect(error).to.be.undefined; }); }); - describe('paginates', function() { - it('with criteria', function() { + describe('paginates', () => { + it('with criteria', () => { return Book.paginate({ title: 'Book #10' }).then((result) => { - console.log('with criteria logging =================='); - console.log('result:', result); expect(result.docs).to.have.length(1); expect(result.docs[0].title).to.equal('Book #10'); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with default options (page=1, limit=10, lean=false)', function() { - return Book.paginate().then(function(result) { + it('with default options (page=1, limit=10, lean=false)', () => { + return Book.paginate().then((result) => { expect(result.docs).to.have.length(10); expect(result.docs[0]).to.be.an.instanceof(mongoose.Document); expect(result.total).to.equal(100); expect(result.limit).to.equal(10); expect(result.page).to.equal(1); - expect(result.pages).to.equal(10); expect(result.offset).to.equal(0); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with custom default options', function() { + it('with custom default options', () => { mongoosePaginate.paginate.options = { limit: 20, lean: true }; - return Book.paginate().then(function(result) { + return Book.paginate().then((result) => { expect(result.docs).to.have.length(20); expect(result.limit).to.equal(20); expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); + delete mongoosePaginate.paginate.options; + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with offset and limit', function() { - return Book.paginate({}, { offset: 30, limit: 20 }).then(function(result) { + it('with offset and limit', () => { + return Book.paginate({}, { offset: 30, limit: 20 }).then((result) => { expect(result.docs).to.have.length(20); expect(result.total).to.equal(100); expect(result.limit).to.equal(20); expect(result.offset).to.equal(30); expect(result).to.not.have.property('page'); expect(result).to.not.have.property('pages'); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with page and limit', function() { - return Book.paginate({}, { page: 1, limit: 20 }).then(function(result) { + it('with page and limit', () => { + return Book.paginate({}, { page: 1, limit: 20 }).then((result) => { expect(result.docs).to.have.length(20); expect(result.total).to.equal(100); expect(result.limit).to.equal(20); expect(result.page).to.equal(1); expect(result.pages).to.equal(5); expect(result).to.not.have.property('offset'); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with zero limit', function() { - return Book.paginate({}, { page: 1, limit: 0 }).then(function(result) { + it('with zero limit', () => { + return Book.paginate({}, { page: 1, limit: 0 }).then((result) => { expect(result.docs).to.have.length(0); expect(result.total).to.equal(100); expect(result.limit).to.equal(0); @@ -125,43 +130,55 @@ describe('mongoose-paginate', function() { expect(result.pages).to.equal(Infinity); }); }); - it('with select', function() { - return Book.paginate({}, { select: 'title' }).then(function(result) { + it('with select', () => { + return Book.paginate({}, { select: 'title' }).then((result) => { expect(result.docs[0].title).to.exist; expect(result.docs[0].date).to.not.exist; + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with sort', function() { - return Book.paginate({}, { sort: { date: -1 } }).then(function(result) { + it('with sort', () => { + return Book.paginate({}, { sort: { date: -1 } }).then((result) => { expect(result.docs[0].title).to.equal('Book #100'); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with populate', function() { - return Book.paginate({}, { populate: 'author' }).then(function(result) { + it('with populate', () => { + return Book.paginate({}, { populate: 'author' }).then((result) => { expect(result.docs[0].author.name).to.equal('Arthur Conan Doyle'); + }, (error) => { + expect(error).to.be.undefined; }); }); - describe('with lean', function() { - it('with default leanWithId=true', function() { - return Book.paginate({}, { lean: true }).then(function(result) { + describe('with lean', () => { + it('with default leanWithId=true', () => { + return Book.paginate({}, { lean: true, leanWithId: true }).then((result) => { expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); expect(result.docs[0].id).to.equal(String(result.docs[0]._id)); + }, (error) => { + expect(error).to.be.undefined; }); }); - it('with leanWithId=false', function() { - return Book.paginate({}, { lean: true, leanWithId: false }).then(function(result) { - expect(result.docs[0]).to.not.be.an.instanceof(mongoose.Document); - expect(result.docs[0]).to.not.have.property('id'); + it('with lean without leanWithId', () => { + return Book.paginate({}, { + lean: true + }).then((result) => { + expect(result.docs).to.not.be.an.instanceof(mongoose.Document); + expect(result.docs).to.not.have.property('id'); + }, (error) => { + expect(error).to.be.undefined; }); }); }); }); - after(function(done) { + after((done) => { mongoose.connection.db.dropDatabase(done); }); - after(function(done) { + after((done) => { mongoose.disconnect(done); });