import {WrappingError} from "./Utils"; export default class Pagination { public readonly page: number; public readonly perPage: number; public readonly totalCount: number; public constructor(page: number, perPage: number, totalCount: number) { if (perPage <= 0) throw new Error('perPage must be >= 1'); if (totalCount < 0) throw new Error('totalCount must be >= 0'); this.page = page; this.perPage = perPage; this.totalCount = totalCount; if (this.page < 1 || this.page > 1 && this.page > this.lastPage) { throw new PageNotFoundError(this.page); } } public hasPrevious(): boolean { return this.page > 1; } public hasNext(): boolean { return this.page < this.lastPage; } public get lastPage(): number { return Math.max(Math.ceil(this.totalCount / this.perPage), 1); } public previousPages(contextSize: number): number[] { const pages = []; let i = 1; // Leftmost context while (i < this.page && i <= contextSize) { pages.push(i); i++; } // Ellipsis if (i < this.page - contextSize) { pages.push(-1); } // Middle left context i = Math.max(i, this.page - contextSize); while (i < this.page) { pages.push(i); i++; } return pages; } public nextPages(contextSize: number): number[] { const pages = []; let i = this.page + 1; // Middle right context while (i <= this.lastPage && i <= this.page + contextSize) { pages.push(i); i++; } // Ellipsis if (this.page + contextSize + 1 < this.lastPage - contextSize + 1) { pages.push(-1); } // Rightmost context i = Math.max(i, this.lastPage - contextSize + 1); while (i <= this.lastPage) { pages.push(i); i++; } return pages; } } export class PageNotFoundError extends WrappingError { public constructor( public readonly page: number, ) { super(`Page ${page} not found.`); } }