npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

express-pagify

v1.0.0

Published

A simple and flexible Express middleware for API pagination

Downloads

13

Readme

express-pagify

A simple and flexible Express middleware for API pagination

npm version

Table of Contents

Installation

This package is distributed via the npm registry.

Make sure you have Node.js 18 or higher installed.

If this is a new project, initialize it with:

npm init -y

Then run:

npm install express-pagify

Configuration

Offset-based middleware (pagify)

| Option | Type | Default | Description | | ------------------------ | --------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | fallBackValues | object \| false | false | Defines default pagination values. If set to false, fallbacks are disabled, and an error is thrown when any value is invalid. | | invalidValuesMessage | string | "One or more required paginated values are missing" | Error message to be used when invalid pagination parameters are encountered | | supportedHttpMethods | string[] | ["GET"] | Restrict pagination middleware to specific HTTP methods. | | pageParamName | string | "page" | Name of the query parameter that defines the current page. | | pageSizeParamName | string | "pageSize" | Name of the query parameter that defines the number of items per page. | | validatorFunction | (page: number, pageSize: number) => boolean | (page, pageSize) => true | A custom validation function for pagination parameters. If provided, it will be called with the raw query param value. Must return true for valid values and false otherwise. |

Fallback Values

The fallBackValues object allows you to define defaults for each pagination property.

| Key | Type | Description | | -------------------- | -------- | ------------------------------------------------------- | | defaultPageValue | number | Used when page query param is missing or invalid. | | defaultPageSizeValue | number | Used when pageSize query param is missing or invalid. |

Cursor-based middleware (pagifyCursorBased)

The configuration object used by the cursor-based pagination middleware.
T represents the decoded cursor object, e.g. { last: string; limit: number }.

| Option | Type | Default | Description | | ------------------------ | ------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------- | | fallBackValues | object \| false | false | Defines default pagination values. If false, fallback is disabled and throws an error. | | invalidValuesMessage | string | "One or more required paginated values are missing" | Error message to be used when invalid pagination parameters are encountered | | supportedHttpMethods | string[] | ["GET"] | Restrict pagination middleware to specific HTTP methods. | | cursorParamName | string | "c" | Name of the query parameter that contains the Base64 cursor. | | lastPropertyName | keyof T | "last" | Property in the cursor that represents the "last seen" item. | | limitPropertyName | keyof T | "limit" | Property in the cursor that represents the page size. | | validatorFunction | (cursor: T \| undefined) => boolean | (cursor) => true | A custom validation function that validates cursor values. |

Fallback Values

The fallBackValues object allows you to define defaults for each pagination property.

| Key | Type | Description | | ------------ | ---------------------------------- | ---------------------------------------------------------------- | | defaultLast | string \| number \| Date \| null | Used when the last value in the cursor is missing or invalid. | | defaultLimit | number | Used when the limit value in the cursor is missing or invalid. |

Usage

Offset-based (pagify)

This middleware reads selected pagination parameters from the query string, validates them, and attaches a standardized pagination object to the req object for downstream handlers to use.

import express from 'express';
import { pagify } from 'express-pagify';

const app = express();

app.use(
  pagify({
    pageParamName: 'page', // query param for current page
    pageSizeParamName: 'pageSize', // query param for page size
  })
);

app.get('/items', (req, res) => {
  // req.pagination will always be normalized and validated
  const { page, pageSize, skip, take } = req.pagination;

  // Example: fetch items with your DB client
  // const items = await db.getItems({ skip, take });

  res.json({ page, pageSize, skip, take, data: [] });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Cursor-based (pagifyCursorBased)

This middleware handles cursor-based pagination. It reads a Base64-encoded cursor from the query string, decodes it, validates it, and attaches it to req.pagination.cursor for downstream handlers.

import express from 'express';
import { pagifyCursorBased } from 'express-pagify';
import { type MyCursorType } from './types/MyCursorType.ts';

const app = express();

app.get(
  '/items',
  pagifyCursorBased<MyCursorType>({
    cursorParamName: 'cursor',
    validatorFunction: (cursor) => !!cursor?.last && cursor.limit > 0,
    fallBackValues: { defaultLast: null, defaultLimit: 20 },
  }),
  (req, res) => {
    // Access parsed cursor
    const { cursor } = req.pagination;
    const { last, limit } = cursor;

    // Example: fetch items with your DB client
    // const items = await db.getItems({ last, limit });

    res.json({ cursor, data: [] });
  }
);

app.listen(3000, () => console.log('Server running on port 3000'));

Response Helpers

In addition to the pagination middlewares, the package provides helper functions to send standardized paginated responses.

Offset-based pagination response

Sends a response using offset-based pagination.

offsetBasedResponse<T>({
  res,
  data,
  skip,
  take,
  total,
  status = 200,
  extra = {},
});

| Key | Type | Description | | -------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | res | Response | Express response object where the paginated result will be sent. | | data | T[] | Array of paginated items (the current page of results). | | skip | number | Number of items skipped before this page (can be obtained from req.pagination.skip if the middleware is active). | | take | number | Number of items requested for this page (can be obtained from req.pagination.take if the middleware is active). | | total | number | Total number of items available in the collection. | | status | number (optional, default: 200) | HTTP status code for the response. | | extra | object (optional) | Additional fields to merge into the response object. |

Example:

import { type Items } from './types/Items';

const items = await prisma.user.findMany({ skip, take });
const total = await prisma.user.count();

offsetBasedResponse<Items[]>({
  res,
  data: items,
  skip,
  take,
  total,
  status: 200,
  extra: {
    cool: true,
  },
});

Response Shape:

  {
    data: T[];
    pagination: {
      page: number;
      pageSize: number;
      skip: number;
      total: number;
      totalPages: number;
      hasNext: boolean;
      hasPrevious: boolean;
    };
    // Extra fields merged into the response
    [key: string]: any;
  }

Cursor-based pagination response

Sends a response using cursor-based pagination.

cursorBasedResponse<T>({
  res,
  data,
  nextCursor,
  prevCursor,
  limit,
  count,
  status = 200,
  extra = {},
});

| Key | Type | Description | | ------------ | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | res | Response | Express response object where the paginated result will be sent. | | data | T[] | Array of paginated items (the current page of results). | | nextCursor | object \| null | Cursor object for the next page (Base64 encoded internally), or null if none. | | prevCursor | object \| null | Cursor object for the previous page (Base64 encoded internally), or null if none. | | limit | number | Maximum number of items per page (can be obtained from the property defined in the cursor, e.g., req.pagination.cursor.limit, if the middleware is active). | | count | number | Number of items returned in the current response. | | status | number (optional, default: 200) | HTTP status code for the response. | | extra | object (optional) | Additional fields to merge into the response object. |

Example:

import { type Items } from './types/Items';

const items = await prisma.user.findMany({ take: 20 });
const count = items.length;

cursorBasedResponse<Items[]>({
  res,
  data: items,
  nextCursor: null,
  prevCursor: { id: 10 }, // internally encoded as Base64 string
  limit: 20,
  count,
  status: 200,
  extra: {
    cool: true,
  },
});

Response Shape:

{
  data: T[];
  pagination: {
  nextCursor: string | null;
  prevCursor: string | null;
  hasNext: boolean;
  hasPrevious: boolean;
  limit: number;
  count: number;
  };
  // Extra fields merged into the response
  [key: string]: any;
}