Express/MongoDB backend with JWT auth, RBAC, S3 uploads, notifications, and scheduled jobs.
70 lines
1.7 KiB
JavaScript
70 lines
1.7 KiB
JavaScript
// /utils/pagination.js
|
|
|
|
const parsePaginationAndSort = (query, defaultSortBy = 'createdAt', defaultSortOrder = 'desc', maxLimit = 100) => {
|
|
const page = Math.max(1, parseInt(query.page, 10) || 1);
|
|
let limit = parseInt(query.limit, 10) || 20;
|
|
if (limit <= 0) limit = 20;
|
|
if (limit > maxLimit) limit = maxLimit;
|
|
|
|
const skip = (page - 1) * limit;
|
|
|
|
const sortBy = query.sortBy || defaultSortBy;
|
|
const sortOrder = (query.sortOrder || defaultSortOrder).toLowerCase() === 'asc' ? 1 : -1;
|
|
|
|
const sort = {};
|
|
sort[sortBy] = sortOrder;
|
|
|
|
return {
|
|
page,
|
|
limit,
|
|
skip,
|
|
sort
|
|
};
|
|
};
|
|
|
|
const buildFilterQuery = (query, searchFields = [], excludedKeys = ['page', 'limit', 'sortBy', 'sortOrder', 'q', 'lang']) => {
|
|
const filter = {};
|
|
|
|
// Build field-based exact or boolean filters
|
|
Object.keys(query).forEach((key) => {
|
|
if (!excludedKeys.includes(key) && query[key] !== undefined && query[key] !== '') {
|
|
const val = query[key];
|
|
if (val === 'true') {
|
|
filter[key] = true;
|
|
} else if (val === 'false') {
|
|
filter[key] = false;
|
|
} else if (!isNaN(val) && String(Number(val)) === val) {
|
|
filter[key] = Number(val);
|
|
} else {
|
|
filter[key] = val;
|
|
}
|
|
}
|
|
});
|
|
|
|
// Build regex search for ?q= across defined text fields
|
|
if (query.q && searchFields.length > 0) {
|
|
const searchRegex = new RegExp(query.q, 'i');
|
|
filter.$or = searchFields.map((field) => ({
|
|
[field]: searchRegex
|
|
}));
|
|
}
|
|
|
|
return filter;
|
|
};
|
|
|
|
const calculateMeta = (totalCount, page, limit) => {
|
|
const totalPages = Math.ceil(totalCount / limit) || 0;
|
|
return {
|
|
totalCount,
|
|
totalPages,
|
|
currentPage: page,
|
|
limit
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
parsePaginationAndSort,
|
|
buildFilterQuery,
|
|
calculateMeta
|
|
};
|