@nestarc/pagination
Prisma cursor & offset pagination for NestJS with filtering, sorting, search, and Swagger auto-documentation.
Choosing between the two modes? Read the measured cursor vs offset pagination comparison for Prisma before setting a default for your endpoints.
For feeds ordered by createdAt, start with the keyset cursor example. Use offset pagination when users need numbered pages, and install the module before adding either endpoint.
Features
- Offset + cursor pagination in a single API
- Keyset cursors for stable pagination on non-unique sort columns with tie-breakers
- Count strategies — exact, omitted, or custom totals for cost-aware queries
- 12 filter operators:
$eq,$ne,$gt,$gte,$lt,$lte,$in,$nin,$ilike,$btw,$null,$not:null - Multi-column sorting with null positioning
- Full-text search across multiple columns
- Column/operator whitelisting for security
- Swagger auto-documentation (optional)
- Standalone
paginate()function — works without NestJS - Prisma 7-first compatibility, with Prisma 5 and 6 retained in the peer range
- Compatible with
@nestarc/tenancy(RLS) and@nestarc/soft-deletevia Prisma extension chain
Quick Start
Install
bash
npm install @nestarc/paginationPeer dependencies: @nestjs/common, @nestjs/core, @prisma/client 5/6/7, reflect-metadata, rxjs
Prisma 7 is the primary generated-client and CI target. Prisma 5 and 6 remain accepted peer versions for existing applications.
1. Register the module
typescript
import { PaginationModule } from '@nestarc/pagination';
@Module({
imports: [
PaginationModule.forRoot({
defaultLimit: 20,
maxLimit: 100,
}),
],
})
export class AppModule {}2. Use in a controller
typescript
import { Paginate, PaginateQuery, ApiPaginatedResponse } from '@nestarc/pagination';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get()
@ApiPaginatedResponse(UserDto)
async findAll(@Paginate() query: PaginateQuery) {
return this.userService.findAll(query);
}
}3. Use in a service
typescript
import { paginate, PaginateQuery, PaginateConfig, Paginated } from '@nestarc/pagination';
@Injectable()
export class UserService {
constructor(private readonly prisma: PrismaService) {}
async findAll(query: PaginateQuery): Promise<Paginated<User>> {
return paginate(query, this.prisma.user, {
sortableColumns: ['id', 'name', 'email', 'createdAt'],
defaultSortBy: [['createdAt', 'DESC']],
searchableColumns: ['name', 'email'],
filterableColumns: {
role: ['$eq', '$in'],
createdAt: ['$gte', '$lte'],
},
});
}
}