Drizzle API Reference
Functions exported by @evensurface/paginate-drizzle, with options and results.
These functions come from @evensurface/paginate-drizzle, not the framework-independent core. They let you pass Drizzle query builders directly without writing a custom adapter.
import {
paginate,
paginateOffset,
paginateCursor,
createDrizzleAdapter,
createDrizzleCursorAdapter,
isDrizzlePaginationError,
} from "@evensurface/paginate-drizzle"paginate(options)
Uses a Drizzle select-query factory and a matching count query to return one numbered page.
- Input:
DrizzlePaginationOptions<TItem>:query,countQuery, optionalpage,limit,pageSizeOptions. - Output:
Promise<PaginatedResult<TItem>>.
const result = await paginate({
query: () => db.select().from(users).orderBy(asc(users.id)),
countQuery: db.$count(users),
page: 2,
limit: 20,
})db, users, and asc are from your Drizzle setup; see Drizzle ORM Adapter for complete imports and schema examples. query is a function because each fetch needs a fresh query builder. countQuery is the query to await, not a function that Paginate will call. The selected row type is inferred.
paginateOffset(options)
Works like paginate(), but uses a zero-based offset instead of a numbered page.
- Input:
DrizzleOffsetPaginationOptions<TItem>:query,countQuery, optionaloffset,limit,pageSizeOptions. - Output:
Promise<OffsetPaginatedResult<TItem>>.
const result = await paginateOffset({
query: () => db.select().from(users).orderBy(asc(users.id)),
countQuery: db.$count(users),
offset: 40,
limit: 20,
})It asks Drizzle to skip 40 matching records and return up to 20. If the count is 95, the output metadata is { total: 95, limit: 20, offset: 40, hasNextPage: true, hasPreviousPage: true }.
paginateCursor(options)
Runs forward-only, count-free keyset pagination using Drizzle columns and generated SQL predicates.
- Input:
DrizzleCursorPaginationOptions<TItem>:query,orderBy, optionalcursor,limit,pageSizeOptions. - Output:
Promise<CursorPaginatedResult<TItem>>.
const result = await paginateCursor({
query: ({ cursorWhere, orderBy }) =>
db.select({ id: users.id, createdAt: users.createdAt })
.from(users)
.where(cursorWhere)
.orderBy(...orderBy),
orderBy: [
{ key: "createdAt", column: users.createdAt, direction: "desc", getValue: (row) => row.createdAt },
{ key: "id", column: users.id, direction: "desc", getValue: (row) => row.id },
],
limit: 20,
})The callback receives DrizzleCursorQueryOptions: a generated cursorWhere condition and an array of SQL orderBy expressions. Use both, plus any application-specific filters in .where(and(yourFilter, cursorWhere)). The adapter asks for 21 rows to determine whether another batch exists. For the full walkthrough, see Drizzle Cursor Pagination.
createDrizzleAdapter<TItem>()
Creates a PaginationAdapter you can pass to the core paginate() or paginateOffset() functions. You usually won't need this because the Drizzle package already provides wrapper functions.
- Input: no function arguments. The optional TypeScript generic
TItemis your selected row type. - Output:
PaginationAdapter<DrizzleSelectQueryFactory<TItem>,DrizzleCountQuery, TItem>.
import { paginate as paginateCore } from "@evensurface/paginate"
import { createDrizzleAdapter } from "@evensurface/paginate-drizzle"
type UserRow = { id: number; name: string }
const adapter = createDrizzleAdapter<UserRow>()
const result = await paginateCore({
adapter,
query: () => db.select({ id: users.id, name: users.name }).from(users).orderBy(asc(users.id)),
countQuery: db.$count(users),
page: 1,
limit: 10,
})The adapter's count() accepts a Drizzle $count() result or a one-row select({ total: count() }) result. Its fetch() builds and executes a query with .limit(limit).offset(offset).
createDrizzleCursorAdapter<TItem>(orderBy)
Creates a CursorPaginationAdapter for the core's paginateCursor(). The wrapper in the Drizzle package already calls this for you.
- Input:
orderBy:DrizzleCursorOrder<TItem>, a non-empty array of column ordering definitions. - Output:
CursorPaginationAdapter<DrizzleCursorQueryFactory<TItem>, TItem>.
import { createDrizzleCursorAdapter } from "@evensurface/paginate-drizzle"
const adapter = createDrizzleCursorAdapter<{ id: number }>([
{ key: "id", column: users.id, direction: "asc", getValue: (row) => row.id },
])On fetch, this adapter checks the configured columns and cursor position, creates SQL continuation conditions when necessary, and calls the supplied query factory. On getPosition(item), it extracts each column's value using the getValue functions.
isDrizzlePaginationError(error)
Checks whether an error came from the Drizzle adapter itself.
- Input:
unknown. - Output: a boolean at runtime; TypeScript narrows to
DrizzlePaginationErrorwhentrue.
import { isDrizzlePaginationError } from "@evensurface/paginate-drizzle"
try {
await paginate({
query: () => db.select().from(users).orderBy(asc(users.id)),
countQuery: db.$count(users),
page: 1,
})
} catch (error) {
if (isDrizzlePaginationError(error)) {
console.error(error.code) // e.g. "DRIZZLE_QUERY_REUSED"
} else {
throw error // A database failure or a core pagination error.
}
}This guard does not identify validation errors created by the core. To handle both kinds, use the corresponding isPaginationError() from @evensurface/paginate. The Errors reference lists both sets of codes.
All exported Drizzle interfaces and aliases are described in Drizzle Types.