Express Pagination Middleware

raw JSON →
1.0.2 verified Thu Apr 23 auth: no javascript abandoned

express-paginate is a Node.js middleware and view helper library designed for pagination within Express applications. It provides utilities to handle `req.skip` (aliased as `req.offset`), `req.query.limit`, and `req.query.page` automatically, simplifying the process of fetching paginated results from a database and generating pagination links. The current stable version is 1.0.2, released in 2016. The package has seen no significant updates or active development since then, indicating an effectively abandoned status. It differentiates itself by providing both server-side request parsing for pagination parameters and a view helper function (`paginate.href`) for rendering pagination controls in templates, integrating directly into the Express `req` and `res.locals` objects.

error TypeError: paginate.middleware is not a function
cause Incorrect import statement (e.g., using `import { middleware } from 'express-paginate'` in ESM) or trying to access it before the `require` statement.
fix
Ensure you are using const paginate = require('express-paginate'); and then calling app.use(paginate.middleware(...));.
error Cannot read properties of undefined (reading 'skip') (or similar for 'limit')
cause The `paginate.middleware` was not applied before attempting to access `req.skip` or `req.query.limit` in a route handler, or the middleware failed to execute.
fix
Verify that app.use(paginate.middleware(limit, maxLimit)); is called globally or on the specific routes *before* the route handler that accesses req.skip.
error Error: Can't set headers after they are sent to the client.
cause While not specific to `express-paginate`, this can occur if an error or previous response sends headers before `express-paginate` attempts to modify `res.locals` or if a subsequent middleware/route sends a response after `express-paginate`'s operations were meant to be completed and another response was inadvertently sent.
fix
Review middleware order and ensure only one response is sent per request-response cycle. Place express-paginate early in the middleware chain if it's meant to apply broadly.
breaking The `paginate` middleware sets `req.skip` instead of `req.offset` since v0.1.0, though `req.offset` is internally aliased to `req.skip` for compatibility. Code expecting `req.offset` directly should use `req.skip` or be aware of the alias.
fix Update database queries to use `req.skip` (e.g., `Model.find().skip(req.skip)`).
gotcha Passing `?limit=0` to the pagination middleware will return all results. This can lead to severe performance and security issues (e.g., denial of service attacks) if not explicitly handled.
fix Implement a custom middleware to enforce a minimum or default `limit` value if `req.query.limit` is `0` or too low (e.g., `if (req.query.limit <= 10) req.query.limit = 10;`).
gotcha This package is effectively abandoned, with no new releases or significant development since 2016. It may not be compatible with newer Node.js or Express versions, lacks modern features, and will not receive security updates.
fix Consider migrating to a more actively maintained pagination library or implementing custom pagination logic, especially for new projects or applications requiring robust security and long-term support.
gotcha The package uses CommonJS (`require`). Attempting to use ESM `import` statements directly will not work as expected and can lead to errors when trying to access named exports like `middleware`.
fix Ensure your project or file uses `require('express-paginate')` for importing the library. If using a pure ESM environment, you may need a wrapper or a different library.
npm install express-paginate
yarn add express-paginate
pnpm add express-paginate

This quickstart initializes an Express application with `express-paginate` middleware. It demonstrates how to apply pagination to a dummy dataset, using `req.skip` and `req.query.limit` to slice results, and mentions the `res.locals.paginate.href` helper for generating navigation links. It also includes the recommended security fix for `limit=0`.

const express = require('express');
const paginate = require('express-paginate');
const app = express();

// Dummy data for demonstration
const items = Array.from({ length: 100 }, (_, i) => `Item ${i + 1}`);

app.use(paginate.middleware(10, 50)); // Default limit 10, max limit 50

// Optional: Limit '0' for infinite results can be a security/performance risk
// Add a middleware to prevent it if needed.
app.all('*', (req, res, next) => {
  if (req.query.limit <= 10) {
    req.query.limit = 10;
  }
  next();
});

app.get('/items', (req, res) => {
  const { skip, query } = req;
  const limit = parseInt(query.limit, 10) || 10;
  const page = parseInt(query.page, 10) || 1;

  const paginatedItems = items.slice(skip, skip + limit);
  const itemCount = items.length;
  const pageCount = Math.ceil(itemCount / limit);

  res.json({
    items: paginatedItems,
    page,
    pageCount,
    itemCount,
    pages: paginate.get      // Example of generating page numbers (not directly in express-paginate, usually a helper)
    // For actual previous/next links, use res.locals.paginate.href
    // next_page: res.locals.paginate.href(req)(false, { someFilter: 'value', limit: limit + 5 }),
    // prev_page: res.locals.paginate.href(req)(true)
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}/items`);
  console.log('Try: http://localhost:3000/items?page=2&limit=5');
});