Skip to content

Instantly share code, notes, and snippets.

@axmad386
Created May 17, 2024 14:41
Show Gist options
  • Save axmad386/73bf037609e13b9af2e3d20b6e1b7cd4 to your computer and use it in GitHub Desktop.
Save axmad386/73bf037609e13b9af2e3d20b6e1b7cd4 to your computer and use it in GitHub Desktop.
Fully Typed Drizzle ORM Dynamic Pagination Query

Pagination Helper

This is simple helper for dynamic pagination using drizzle-orm using basic limit offset. The result is fully typed.

import { db } from "../yourdbinstance";
import { sql } from "drizzle-orm";
import type { PgSelect } from "drizzle-orm/pg-core";

interface PaginateParam {
  limit: number;
  page: number;
}
export async function paginateQuery<T extends PgSelect>(
  query: T,
  { limit, page }: PaginateParam,
) {
  const subQuery = query.as("sub");
  const rowCountQuery = db.select({ total: sql<number>`count(*)` }).from(
    subQuery,
  );

  const rowCountResult = await rowCountQuery.execute();
  const rowCount = Number(rowCountResult[0].total);
  const pageCount = Math.ceil(rowCount / limit);

  query.limit(limit).offset((page - 1) * limit);

  const data = (await query.execute()) as Awaited<ReturnType<T["execute"]>>;

  return {
    data,
    pagination: {
      rowCount,
      pageCount,
      page,
      limit,
    },
  };
}

Example Usage

Just pass the dynamic query into the pagination helper. Example:

    const query = db.select({
      id: users.id,
      username: users.username,
      email: users.email,
      created_at: users.created_at,
      full_name: sql`CONCAT(users.first_name, ' ', users.last_name)`.as(
        "full_name",
      ),
    })
      .from(users)
      .leftJoin(roles, eq(users.role_id, roles.id))
      .where(...)
      .orderBy(...);

    const res = await paginateQuery(query.$dynamic(), { limit, page });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment