Documentation

Paginate arrays in Node (and browsers). Returns JSON with data, meta, and links—use it in your return when sending data to users.

Overview

Takes any array and returns JSON data, meta, links. It works with any data source—Mongoose, Prisma, Sequelize, raw SQL, or plain arrays.

Use it in your return when sending data to users. Pagination happens in memory—fetch your dataset, then pass it to paginate() or paginateFromRequest() in res.json().

controller — use in return
// ESM / TypeScript
import { paginateFromRequest } from 'api-paginate';
// CommonJS: const { paginateFromRequest } = require('api-paginate');

const users = await User.find().lean();
return res.json(paginateFromRequest(req, users, { per_page: 15 }));

// returns data, meta, links — ready for users

Installation

Install via npm or yarn:

$ npm install api-paginate

The package ships as CommonJS and ESM. TypeScript types are included.

// CommonJS (Node)
const { paginate } = require('api-paginate');

// ESM / TypeScript
import { paginate } from 'api-paginate';

Passing Data

Accepts any array. Below are common formats from different ORMs.

Mongoose_id, __v
// Use .lean() to get plain objects
const docs = await User.find().lean();
const result = paginate(docs, {
  current_page: 1, per_page: 20, route: '/users'
});
// result.data, result.meta, result.links
PrismacamelCase, id
// findMany returns plain objects by default
const products = await prisma.product.findMany();
const result = paginate(products,
  {
    current_page: 2, per_page: 10, route: '/products'
  });
Sequelize / TypeORMsnake_case, created_at
// Use raw: true for plain row objects
const posts = await Post.findAll({ raw: true });
const result = paginate(posts,
  { current_page: 1, per_page: 15, route: '/posts' });
Raw SQL / Knexflat row objects
// Raw query returns rows; pass array to paginate
const rows = await db.raw('SELECT * FROM orders ORDER BY created_at DESC');
const orders = rows.rows ?? rows;
const result = paginate(orders, { current_page: 3, per_page: 25 });
JSON APInested attributes
// Any array shape works—id, type, attributes, etc.
const items = [
  { id: 'a1', type: 'article', attributes: { title, tags }},
  { id: 'a2', type: 'comment', attributes: { body, author }}
];
const result = paginate(items, { per_page: 5, current_page: 1 });
CSV (client-side)parse to array
// Parse CSV to array of objects, then paginate
const lines = csvText.trim().split('\n');
const headers = lines[0].split(',');
const data = lines.slice(1).map(line => {
  const vals = line.split(',');
  return Object.fromEntries(headers.map((h, i) => [h, vals[i]]));
});
const result = paginate(data, { page: 1, perPage: 10 });

Note: Paginator does not fetch data. Provide a plain array—use .lean(), .toJSON(), or raw: true.

API Reference

paginate(data, options?)

Returns data, meta, and links.

Parameters

ParameterTypeDescription
dataT[]Array to paginate
options.current_pagenumberCurrent page, 1-based (default: 1)
options.per_pagenumberItems per page (default: 15)
options.routestringRoute for links (e.g. /api/users); combined with configured baseUrl or auto-detected origin
options.baseUrlstringOptional override; prefer route + configure
options.pageParamstringQuery param name (default: "page")

Return value

{ data, meta: { current_page, per_page, total, ... }, links: { first, prev, next, last } }

Examples

Express

Configure once in app.ts or server.ts; in route files only use paginateFromRequest.

app.ts or server.ts (entry point)
import { configure } from 'api-paginate';

configure({ baseUrl: process.env.API_BASE_URL });
routes/users.ts (no configure here)
import { paginateFromRequest } from 'api-paginate';

app.get('/users', async (req, res) => {
  try {
    const users = await User.find().lean();
    res.json(paginateFromRequest(req, users, { route: '/users', per_page: 15 }));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

Next.js API route

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const result = paginate(users, {
    current_page: parseInt(searchParams.get('page') || '1'),
    per_page: 15,
    route: '/api/users',
  });
  return Response.json(result);
}

Client-side

import { paginate } from 'api-paginate';

const result = paginate(items, { current_page: 2, per_page: 10, route: '/api/items' });

Try it in the Simulator

See pagination in action—use pre-built fixtures or paste CSV. In your API, use api-paginate in the return (e.g. res.json(paginateFromRequest(...))).

Open Simulator