Pagination API

Offset and cursor pagination across the repository and the query builder

paginate()

typescript
async paginate(
page: number,
pageSize: number,
options: any = {}
): Promise<{ data: T[]; total: number; page: number; pageSize: number }>

Pages are 1-based. The options parameter is typed any and is currently unused. The result echoes page and pageSize back alongside the rows and the total count.

Parameters:

  • page 1-based page number
  • pageSize Rows per page
  • options Typed any, currently unused
example/paginate.ts
const result = await userRepo.paginate(2, 20);
// { data: [...], total: 137, page: 2, pageSize: 20 }

findAndCount()

typescript
async findAndCount(
options: { relations?: string[] } = {}
): Promise<{ data: T[]; total: number }>

Returns every matching row plus the total count. No offset or limit is applied.

example/find-and-count.ts
const { data, total } = await userRepo.findAndCount({
relations: ["posts"],
});

findAndCountAll()

typescript
async findAndCountAll(options?: {
page?: number;
pageSize?: number;
conditions?: Partial<T>;
}): Promise<{ data: T[]; total: number }>

Defaults to page=1 and pageSize=20. It does NOT echo page and pageSize back — it returns only { data, total }.

example/find-and-count-all.ts
const { data, total } = await userRepo.findAndCountAll({
page: 3,
pageSize: 10,
conditions: { active: true },
});

findMany()

typescript
async findMany(options?: {
where?: Partial<T>;
cursor?: {
field: string;
value: any;
direction?: "forward" | "backward";
};
take?: number;
skip?: number;
orderBy?: { field: string; direction: "ASC" | "DESC" };
relations?: string[];
}): Promise<T[]>

Returns a plain array, NOT a { data, total } wrapper. The cursor emits a WHERE col > ? or WHERE col < ? predicate based on direction and orderBy.direction. take becomes LIMIT and skip becomes OFFSET.

example/find-many.ts
const page = await userRepo.findMany({
where: { active: true },
orderBy: { field: "id", direction: "ASC" },
take: 20,
skip: 40,
});
const next = await userRepo.findMany({
cursor: { field: "id", value: lastId, direction: "forward" },
orderBy: { field: "id", direction: "ASC" },
take: 20,
});

QueryBuilder: limits

typescript
limit(limit: number): QueryBuilder<T>
offset(offset: number): QueryBuilder<T>
take(count: number): QueryBuilder<T> // alias for limit
skip(count: number): QueryBuilder<T> // alias for offset
first(): QueryBuilder<T> // limit 1
paginate(page: number, pageSize: number): QueryBuilder<T>
orderBy(column: string, direction: "ASC" | "DESC" = "ASC"): QueryBuilder<T>

Every method is chainable and returns the builder. paginate() sets limit and offset, but does NOT count — run countExec() separately if you need a total.

example/query-builder-pagination.ts
const rows = await userRepo
.find()
.where("active = ?", true)
.orderBy("id", "ASC")
.paginate(2, 20)
.execute(orm.client);
const total = await userRepo
.find()
.where("active = ?", true)
.countExec(orm.client);

QueryBuilder: execution

typescript
async countExec(client: DBClient): Promise<number>
async existsExec(client: DBClient): Promise<boolean>
async execute(client: DBClient, cache?, cacheKey?): Promise<T[]>
toSQL(): { query: string; params: any[] }

toSQL() renders the built statement and its bound parameters without running it — useful for verifying the LIMIT and OFFSET a paginate call produced.

example/to-sql.ts
const { query, params } = userRepo
.find()
.where("active = ?", true)
.limit(20)
.offset(40)
.toSQL();