oa_based/src/helper/paginate/index.ts

142 lines
3.9 KiB
TypeScript
Raw Normal View History

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