Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 6.0 / Node v4.2.4+ Peer Review for v6.0.0 #73

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
779dd55
[package, prep] prep version # for v6.0.0!
edwardhotchkiss Jan 4, 2016
cda8344
[travis, test] test starting on 4.2. reason being for "harmony"
edwardhotchkiss Jan 8, 2016
ff90322
[travis, test] added stable
edwardhotchkiss Jan 8, 2016
0c7c89c
[test] remove console logs
edwardhotchkiss Jan 8, 2016
9020404
[fix, error handling] catch error on promise => callback
edwardhotchkiss Jan 8, 2016
67dc751
[promises] resolve result if no cb
edwardhotchkiss Jan 8, 2016
1fa8a35
[deps] more range on mongoose
edwardhotchkiss Jan 8, 2016
c81fc3e
[license] added @Jokero to license
edwardhotchkiss Jan 9, 2016
8236882
[major, es6] 8 passing, 5 tests failing
edwardhotchkiss Jan 9, 2016
beb90fa
[tests, cleanup] 5 failing tests commented out, fixing and diving deeper
edwardhotchkiss Jan 9, 2016
9c0fd24
[major, tests, fixes] ES6 = 9/13 tests passing
edwardhotchkiss Jan 9, 2016
fadddcf
[fix, tests] all tests working except for totals
edwardhotchkiss Jan 9, 2016
0a139e9
[tests, RC6.0] working, all tests passing
edwardhotchkiss Jan 9, 2016
323fe54
Merge branch 'master' into ES6-6.0
edwardhotchkiss Jan 9, 2016
5a881ae
[regression] revert several features back to 5.0
edwardhotchkiss Jan 10, 2016
7a8a11c
[debug] remove mongoose debug
edwardhotchkiss Jan 10, 2016
7867da7
[limit:0] back to original 5.0 feature set, all tests passing
edwardhotchkiss Jan 11, 2016
d8e8299
[minor] license, removed hanging space
edwardhotchkiss Jan 11, 2016
8581975
Simple way to handle create required promises
lesterzone Apr 29, 2016
3366694
Merge pull request #85 from lesterzone/internal-promises
niftylettuce Sep 29, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
language: node_js

node_js:
- "4.2.4"
- "4.2"
- "stable"

services:
- mongodb
Expand Down
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.
92 changes: 53 additions & 39 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const mongoose = require('mongoose');

/**
* @package mongoose-paginate
* @param {Object} [query={}]
Expand All @@ -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;
Expand All @@ -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;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be wary about this line. Some people like to set mongoose.Promise to their own promise implementation (e.g. bluebird). Overwriting it here would cause them lots of headaches.


module.exports = function(schema) {
schema.statics.paginate = paginate;
};
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]"
Expand Down Expand Up @@ -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"
Expand Down
105 changes: 61 additions & 44 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -48,120 +47,138 @@ 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);
expect(result.page).to.equal(1);
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);
});

Expand Down