Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Created August 23, 2019 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Noitidart/fed343ee8b28a344450bc31aa6d1c7b4 to your computer and use it in GitHub Desktop.
Save Noitidart/fed343ee8b28a344450bc31aa6d1c7b4 to your computer and use it in GitHub Desktop.
const DEFAULT_PER_PAGE = 25;
const DEFAULT_PAGE = 1;
class Paginator {
static describeParams(defaultPerPage = DEFAULT_PER_PAGE) {
return {
page: {
type: 'number',
// TODO: see if I can have sails validate a range on this number
defaultsTo: DEFAULT_PAGE,
description: '1-based, meaning lowest this can be is 1.'
},
perPage: {
type: 'number',
defaultsTo: defaultPerPage
// TODO: see if i can have sails validate a range on this number, maybe make it enum [25, 100, 250]
}
};
}
/**
* @param {Object} pagination
* @param {number} pagination.page
* @param {number} pagination.perPage
*/
static setParams({ page=DEFAULT_PAGE, perPage=DEFAULT_PER_PAGE }) {
const limit = perPage;
const skip = (page - 1) * perPage;
Paginator.NEXT_PARAMS.push({ limit, skip });
}
static getParams() {
return Paginator.NEXT_PARAMS.shift() || {};
}
static saveParams() {
const params = Paginator.getParams();
const restoreParams = () => Paginator.setParams(params);
return restoreParams;
}
/**
*
* @param {*} model
* @param {*} [criteriaOrWhere] - must NOT include "limit" or "skip"
* @param {Array} [populates] - array of populations to run.
* ie: `['masjids']` will run `await Model.find(...).populate('masjids')`.
* ie: `[['masjids', { sort: 'createdAt' }]]` will run `await Model.find(...).populate('masjids', { sort: 'createdAt' })`.
* ie: `['masjids', 'affairs']` will run two populates.
*
* @returns {Object} paginated
* @returns {Object} paginated.results
* @returns {Object} paginated.totalCount
*/
static async find(model, criteriaOrWhere={}, populates=[]) {
const criteria = criteriaOrWhere.hasOwnProperty('where') || criteriaOrWhere.hasOwnProperty('sort')
? {
...criteriaOrWhere,
...Paginator.getParams()
} : {
...Paginator.getParams()
};
let find = model.find(criteria);
for (const populate of populates) {
find = find.populate(...(Array.isArray(populate) ? populate : [populate]));
}
const results = await find;
return {
results,
totalCount: await model.count(criteria.where)
};
}
}
Paginator.NEXT_PARAMS = [];
module.exports = Paginator;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment