UNPKG

@dakohhh/mongoose-paginator

Version:

Mongoose-Class-Paginator is a lightweight, flexible, and TypeScript-friendly pagination utility for Mongoose models. It provides a class-based approach to handling database pagination with support for filtering, sorting, population, projection, and metada

190 lines 6.69 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Paginator = exports.MongoosePaginatorError = exports.CursorPaginator = exports.OffsetPaginator = exports.PageNumberPaginator = exports.BasePaginator = void 0; const mongoose_1 = require("mongoose"); class BasePaginator { constructor(model, args = { filter: {}, sort: { createdAt: -1 }, lean: true }) { this.model = model; this.args = args; } setArgs(args) { this.args = args; return this; } paginate() { return __awaiter(this, void 0, void 0, function* () { throw new MongoosePaginatorError('Method not implemented'); }); } } exports.BasePaginator = BasePaginator; class PageNumberPaginator extends BasePaginator { constructor(model, page = 1, limit = 10, args = { filter: {}, sort: { createdAt: -1 }, lean: true }) { super(model, args); this.page = page; this.limit = limit; } getSkip() { return (this.page - 1) * this.limit; } paginate() { return __awaiter(this, void 0, void 0, function* () { const skip = this.getSkip(); const query = this.model .find(this.args.filter || {}) .sort(this.args.sort || { createdAt: -1 }) .skip(skip) .limit(this.limit) .populate(this.args.populate || []) .select(this.args.projection || {}); // If the `lean` option is true, apply it to the query if (this.args.lean) { query.lean(); } const [items, total] = yield Promise.all([ query, this.model.countDocuments(this.args.filter || {}), ]); const lastPage = Math.ceil(total / this.limit); const currentPage = this.page; return { data: items, meta: { total, lastPage, currentPage, perPage: this.limit, prev: currentPage > 1 ? currentPage - 1 : null, next: currentPage < lastPage ? currentPage + 1 : null, }, }; }); } setPage(page) { this.page = page; return this; } setLimit(limit) { this.limit = limit; return this; } setArgs(args) { this.args = args; return this; } } exports.PageNumberPaginator = PageNumberPaginator; class OffsetPaginator extends BasePaginator { constructor(model, offset, limit, args = { filter: {}, sort: {}, lean: true }) { if (offset % limit !== 0) { throw new MongoosePaginatorError(`Offset must be a multiple of limit)`); } super(model, args); this.offset = offset; this.limit = limit; } setOffset(offset) { this.offset = offset; return this; } setLimit(limit) { this.limit = limit; return this; } paginate() { return __awaiter(this, void 0, void 0, function* () { const query = this.model .find(this.args.filter || {}) .sort(this.args.sort) .skip(this.offset) .limit(this.limit) .populate(this.args.populate || []) .select(this.args.projection || {}); if (this.args.lean) { query.lean(); } const [items, total] = yield Promise.all([ query, this.model.countDocuments(this.args.filter || {}), ]); const lastPage = Math.ceil(total / this.limit); const currentPage = Math.floor(this.offset / this.limit) + 1; return { data: items, meta: { total, lastPage, currentPage, perPage: this.limit, prev: currentPage > 1 ? currentPage - 1 : null, next: currentPage < lastPage ? currentPage + 1 : null, }, }; }); } } exports.OffsetPaginator = OffsetPaginator; class CursorPaginator extends BasePaginator { constructor(model, cursor, limit, args = { filter: {}, lean: true }) { super(model, args); this.cursor = cursor; this.limit = limit; } setCursor(cursor) { this.cursor = cursor; return this; } setLimit(limit) { this.limit = limit; return this; } paginate() { return __awaiter(this, void 0, void 0, function* () { const filter = Object.assign({}, this.args.filter); if (this.cursor) { filter._id = { $gt: new mongoose_1.Types.ObjectId(this.cursor) }; } const query = this.model .find(filter) .sort({ _id: 1 }) .limit(this.limit) .populate(this.args.populate || []) .select(this.args.projection || {}); if (this.args.lean) { query.lean(); } const items = yield query; const lastItem = items[items.length - 1]; return { data: items, meta: { nextCursor: lastItem ? (String(lastItem._id)) : null, }, }; }); } } exports.CursorPaginator = CursorPaginator; class MongoosePaginatorError extends Error { constructor(message) { super(message); this.name = 'MongoosePaginatorError'; } } exports.MongoosePaginatorError = MongoosePaginatorError; /** * @deprecated Please use `PageNumberPaginator` instead. * This will be removed in version 1.1. */ const PaginatorDeprecationNotice = PageNumberPaginator; exports.Paginator = PaginatorDeprecationNotice; //# sourceMappingURL=index.js.map