raphaelfjesus/mongoose-paginator

View on GitHub
index.js

Summary

Maintainability
A
3 hrs
Test Coverage
'use strict';

module.exports = function(schema, schemaOptions) {
  
  schema.static('paginate', function(criteria, options, callback) {
      var self = this;
      var callback = options && typeof options === 'function' ? options : callback;
      
      var o = buildOptions(options, schemaOptions);
      o.sort = o.convertSort(o.sort, schema);
      criteria = o.criteriaWrapper(o.convertCriteria(criteria, schema));
      
      var promise = new Promise(function(resolve, reject) {
        let resultFn = (err, count, docs) => {
          let result = { total: count, limit: o.limit || count, page: o.page, data: docs };
          
          if(err) {
            callback && callback(err);
            return reject(err);
          }
          
          callback && callback(null, result);
          return resolve(result);
        };

        self.where(criteria).count().exec().then(function(count) {
          if(count <= 0) { return resultFn(null, count, {}); }
          
          let query = self.find(criteria).select(o.select).populate(o.populate).lean(o.lean).skip(o.skip);
          if(o.sort) { query.sort(o.sort); }
          if(o.limit && o.limit > 0) { query.limit(o.limit); }
          
          query.exec().then(function(docs) {
            return resultFn(null, count, docs);
        });
        }, function(err) { resultFn(err); });
      });

      return promise;
  });
};

function buildOptions(options, schemaOptions) {
    var o = Object.assign({}, options || {}, schemaOptions || {});

    // Basic options
    o.limit = o.limit && typeof o.limit === 'function' ? o.limit(o.maxLimit) : ((o.limit && o.maxLimit && o.limit > o.maxLimit) || !o.limit ? o.maxLimit : o.limit);
    o.page = o.page || 1;
    o.skip = (o.page - 1) * (o.limit || 0);
    o.lean = o.lean !== undefined ? o.lean : true; // Plain object, more peformance
    o.select = o.select && typeof o.select === 'function' ? o.select() : o.select;
    o.populate = o.populate && typeof o.populate === 'function' ? o.populate() : (o.populate || '');
    
    // Advanced options
    var convert = (converter) => { return converter && typeof converter === 'function' ? converter : function (value, schema) { return value; }; };
    o.convertSort = convert(o.convertSort);
    o.convertCriteria = convert(o.convertCriteria);
    o.criteriaWrapper = o.criteriaWrapper && typeof o.criteriaWrapper === 'function' ? o.criteriaWrapper : function (criteria) { return criteria; };
    
    return o;
}