import { FindManyOptions, FindOptionsWhere, ObjectLiteral, Repository, SelectQueryBuilder, } from 'typeorm'; import { createPaginationObject } from './create-pagination'; import { IPaginationOptions, PaginationTypeEnum } from './interface'; import { Pagination } from './pagination'; const DEFAULT_LIMIT = 10; const DEFAULT_PAGE = 1; function resolveOptions(options: IPaginationOptions): [number, number, PaginationTypeEnum] { const { page, pageSize, paginationType } = options; return [ page || DEFAULT_PAGE, pageSize || DEFAULT_LIMIT, paginationType || PaginationTypeEnum.TAKE_AND_SKIP, ]; } async function paginateRepository( repository: Repository, options: IPaginationOptions, searchOptions?: FindOptionsWhere | FindManyOptions ): Promise> { const [page, limit] = resolveOptions(options); const promises: [Promise, Promise | undefined] = [ repository.find({ skip: limit * (page - 1), take: limit, ...searchOptions, }), undefined, ]; const [items, total] = await Promise.all(promises); return createPaginationObject({ items, totalItems: total, currentPage: page, limit, }); } async function paginateQueryBuilder( queryBuilder: SelectQueryBuilder, options: IPaginationOptions ): Promise> { const [page, limit, paginationType] = resolveOptions(options); if (paginationType === PaginationTypeEnum.TAKE_AND_SKIP) queryBuilder.take(limit).skip((page - 1) * limit); else queryBuilder.limit(limit).offset((page - 1) * limit); const [items, total] = await queryBuilder.getManyAndCount(); return createPaginationObject({ items, totalItems: total, currentPage: page, limit, }); } export async function paginateRaw( queryBuilder: SelectQueryBuilder, options: IPaginationOptions ): Promise> { const [page, limit, paginationType] = resolveOptions(options); const promises: [Promise, Promise | undefined] = [ (paginationType === PaginationTypeEnum.LIMIT_AND_OFFSET ? queryBuilder.limit(limit).offset((page - 1) * limit) : queryBuilder.take(limit).skip((page - 1) * limit) ).getRawMany(), queryBuilder.getCount(), ]; const [items, total] = await Promise.all(promises); return createPaginationObject({ items, totalItems: total, currentPage: page, limit, }); } export async function paginateRawAndEntities( queryBuilder: SelectQueryBuilder, options: IPaginationOptions ): Promise<[Pagination, Partial[]]> { const [page, limit, paginationType] = resolveOptions(options); const promises: [Promise<{ entities: T[]; raw: T[] }>, Promise | undefined] = [ (paginationType === PaginationTypeEnum.LIMIT_AND_OFFSET ? queryBuilder.limit(limit).offset((page - 1) * limit) : queryBuilder.take(limit).skip((page - 1) * limit) ).getRawAndEntities(), queryBuilder.getCount(), ]; const [itemObject, total] = await Promise.all(promises); return [ createPaginationObject({ items: itemObject.entities, totalItems: total, currentPage: page, limit, }), itemObject.raw, ]; } export async function paginate( repository: Repository, options: IPaginationOptions, searchOptions?: FindOptionsWhere | FindManyOptions ): Promise>; export async function paginate( queryBuilder: SelectQueryBuilder, options: IPaginationOptions ): Promise>; export async function paginate( repositoryOrQueryBuilder: Repository | SelectQueryBuilder, options: IPaginationOptions, searchOptions?: FindOptionsWhere | FindManyOptions ) { return repositoryOrQueryBuilder instanceof Repository ? paginateRepository(repositoryOrQueryBuilder, options, searchOptions) : paginateQueryBuilder(repositoryOrQueryBuilder, options); }