UNPKG

@hosoft/restful-api-framework

Version:

Base framework of the headless cms HoServer provided by http://helloreact.cn

140 lines (118 loc) 4.22 kB
/* eslint-disable no-prototype-builtins */ const Promise = require('bluebird') /** * @param {Object} [query={}] * @param {Object} [options={}] * @param {Object|String} [options.select] * @param {Object|String} [options.sort] * @param {Object|String} [options.customLabels] * @param {Object|} [options.collation] * @param {Array|Object|String} [options.populate] * @param {Boolean} [options.lean=false] * @param {Boolean} [options.leanWithId=true] * @param {Number} [options.offset=0] - Use offset or page to set skip position * @param {Number} [options.page=1] * @param {Number} [options.limit=10] * @param {Function} [callback] * * @returns {Promise} */ function paginate(query, options, callback) { query = query || {} options = Object.assign({}, paginate.options, options) options.customLabels = options.customLabels ? options.customLabels : {} const select = options.select const sort = options.sort const collation = options.collation const populate = options.populate const lean = options.lean || false const leanWithId = options.hasOwnProperty('leanWithId') ? options.leanWithId : false const limit = options.hasOwnProperty('limit') ? options.limit : 10 let skip let offset let page // Custom Labels const labelTotal = 'total' const labelLimit = 'pageSize' const labelPage = 'current' const labelPagination = 'pagination' const labelTotalPages = 'pages' const labelDocs = 'list' const labelNextPage = 'next' const labelPrevPage = 'prev' if (options.hasOwnProperty('offset')) { offset = options.offset skip = offset } else if (options.hasOwnProperty('page')) { page = options.page skip = (page - 1) * limit } else { offset = 0 page = 1 skip = offset } const promises = { docs: Promise.resolve([]), count: this.countDocuments(query).exec() } if (limit) { query = this.find(query).select(select).sort(sort).collation(collation).skip(skip).limit(limit).lean(lean) if (populate) { ;[].concat(populate).forEach(function (item) { query.populate(item) }) } promises.docs = query.exec() if (lean && leanWithId) { promises.docs = promises.docs.then(function (docs) { docs.forEach(function (doc) { doc.id = String(doc._id) }) return docs }) } } return Promise.props(promises) .then(function (data) { const result = { [labelDocs]: data.docs, [labelPagination]: { [labelTotal]: data.count, [labelLimit]: limit } } if (offset !== undefined) { result[labelPagination].offset = offset } if (page !== undefined) { const pages = Math.ceil(data.count / limit) || 1 result.has_prev = false result.has_next = false result[labelPagination][labelPage] = page result[labelPagination][labelTotalPages] = pages // Set prev page if (page > 1) { result.has_prev = true result[labelPagination][labelPrevPage] = page - 1 } else { result[labelPagination][labelPrevPage] = undefined } // Set next page if (page < pages) { result.has_next = true result[labelPagination][labelNextPage] = page + 1 } else { result[labelPagination][labelNextPage] = undefined } } return result }) .asCallback(callback) } /** * @param {Schema} schema */ module.exports = function (schema) { schema.statics.paginate = paginate } module.exports.paginate = paginate