Spaces:
Running
Running
File size: 1,825 Bytes
634b9bb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | class APIFeatures {
constructor(query, queryString) {
this.query = query;
this.queryString = queryString;
}
filter() {
// eslint-disable-next-line node/no-unsupported-features/es-syntax
const queryObj = { ...this.queryString };
const excludedFields = ['page', 'sort', 'limit', 'fields'];
excludedFields.forEach((el) => delete queryObj[el]);
// Advanced filtering
let queryStr = JSON.stringify(queryObj);
queryStr = queryStr.replace(/\b(gte|gt|lte|lt)\b/g, (match) => `$${match}`);
const parsedQuery = JSON.parse(queryStr);
// If the user searches by name → use regex for partial match
if (parsedQuery.nameAr) {
parsedQuery.nameAr = { $regex: parsedQuery.nameAr, $options: 'i' }; // 'i' = ignore case
}
this.query = this.query.find(parsedQuery);
return this;
}
sort() {
if (this.queryString.sort) {
const sortBy = this.queryString.sort.split(',').join(' ');
this.query = this.query.sort(sortBy);
} else {
// Default: sort by newest first, with _id as tiebreaker for stable pagination
// This ensures consistent ordering when multiple products have the same createdAt
this.query = this.query.sort('-createdAt _id');
}
return this;
}
limitFields() {
if (this.queryString.fields) {
const fields = this.queryString.fields.split(',').join(' ');
this.query = this.query.select(fields);
} else {
// FIXME: exclude __v field by default
this.query = this.query.select('-__v');
}
return this;
}
paginate() {
const page = this.queryString.page * 1 || 1;
const limit = this.queryString.limit * 1 || 100;
const skip = (page - 1) * limit;
this.query = this.query.skip(skip).limit(limit);
return this;
}
}
module.exports = APIFeatures;
|