Skip to content

@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-delete via Prisma extension chain

Quick Start ​

Install ​

bash
npm install @nestarc/pagination

Peer 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'],
      },
    });
  }
}

Released under the MIT License.