From 2ec0c7ae8c38a85b73a43ae0b051ef12fc101e2d Mon Sep 17 00:00:00 2001 From: titanism <101466223+titanism@users.noreply.github.com> Date: Mon, 2 Sep 2024 15:39:19 -0500 Subject: [PATCH] feat: CJS rewrite, node v16+ supported, drop all dependencies (now zero deps), use ctx.href vs. ctx.originalUrl --- .babelrc | 4 -- .commitlintrc.js | 3 + .editorconfig | 9 +++ .eslintignore | 2 - .eslintrc | 3 - .gitattributes | 1 + .github/FUNDING.yml | 4 -- .github/workflows/ci.yml | 24 +++++++ .gitignore | 22 +++--- .lintstagedrc.js | 5 ++ .npmignore | 1 - .npmrc | 1 + .prettierrc.js | 5 ++ .remarkignore | 1 + .remarkrc.js | 3 + .xo-config.js | 5 ++ LICENSE | 2 +- Readme.md => README.md | 96 +++++++++++++------------- index.js | 143 +++++++++++++++++++++++++++++++++++++++ package.json | 45 +++++++----- src/index.js | 126 ---------------------------------- test/test.js | 27 ++++++++ 22 files changed, 314 insertions(+), 218 deletions(-) delete mode 100644 .babelrc create mode 100644 .commitlintrc.js create mode 100644 .editorconfig delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 .gitattributes delete mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .lintstagedrc.js delete mode 100644 .npmignore create mode 100644 .npmrc create mode 100644 .prettierrc.js create mode 100644 .remarkignore create mode 100644 .remarkrc.js create mode 100644 .xo-config.js rename Readme.md => README.md (71%) create mode 100644 index.js delete mode 100644 src/index.js create mode 100644 test/test.js diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 0b99782..0000000 --- a/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": [ "crocodile" ], - "sourceMaps": [ "inline" ] -} diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..c34aa79 --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'] +}; diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6c8b36 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 15d2647..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -lib -coverage diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index d878b98..0000000 --- a/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "crocodile" -} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 5b259b1..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,4 +0,0 @@ -# These are supported funding model platforms - -github: niftylettuce -patreon: niftylettuce diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b070751 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI +on: + - push + - pull_request +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + node_version: + - 18 + name: Node ${{ matrix.node_version }} on ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node_version }} + - name: Install dependencies + run: npm install + - name: Run tests + run: npm run test diff --git a/.gitignore b/.gitignore index 6a6d7a5..bfa34c1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,14 @@ - -# osx .DS_Store - -# project -node_modules/ -logs *.log -npm-debug.log* -*.idea -coverage/ -lib +.idea +node_modules +coverage +.nyc_output +locales/ +package-lock.json +yarn.lock + +Thumbs.db +tmp/ +temp/ +*.lcov diff --git a/.lintstagedrc.js b/.lintstagedrc.js new file mode 100644 index 0000000..bdb698a --- /dev/null +++ b/.lintstagedrc.js @@ -0,0 +1,5 @@ +module.exports = { + "*.md": filenames => filenames.map(filename => `remark ${filename} -qfo`), + 'package.json': 'fixpack', + '*.js': 'xo --fix' +}; diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 8eba6c8..0000000 --- a/.npmignore +++ /dev/null @@ -1 +0,0 @@ -src/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..97a92d4 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,5 @@ +module.exports = { + singleQuote: true, + bracketSpacing: true, + trailingComma: 'none' +}; diff --git a/.remarkignore b/.remarkignore new file mode 100644 index 0000000..3dca3a4 --- /dev/null +++ b/.remarkignore @@ -0,0 +1 @@ +test/snapshots/**/*.md diff --git a/.remarkrc.js b/.remarkrc.js new file mode 100644 index 0000000..487138c --- /dev/null +++ b/.remarkrc.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: ['preset-github'] +}; diff --git a/.xo-config.js b/.xo-config.js new file mode 100644 index 0000000..f35c15b --- /dev/null +++ b/.xo-config.js @@ -0,0 +1,5 @@ +module.exports = { + prettier: true, + space: true, + extends: ['xo-lass'] +}; diff --git a/LICENSE b/LICENSE index f7de692..55d4210 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2016- Nick Baugh (http://niftylettuce.com/) +Copyright (c) 2016 Forward Email LLC (https://forwardemail.net) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/Readme.md b/README.md similarity index 71% rename from Readme.md rename to README.md index 557992a..bfe0ee1 100644 --- a/Readme.md +++ b/README.md @@ -1,32 +1,50 @@ -# ctx-paginate +# [**ctx-paginate**](https://github.com/koajs/ctx-paginate) -[![NPM Version][npm-image]][npm-url] -[![NPM Downloads][downloads-image]][downloads-url] -[![MIT License][license-image]][license-url] -[![Slack][slack-image]][slack-url] +[![build status](https://github.com/koajs/ctx-paginate/actions/workflows/ci.yml/badge.svg)](https://github.com/koajs/ctx-paginate/actions/workflows/ci.yml) +[![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo) +[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) +[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org) +[![license](https://img.shields.io/github/license/koajs/ctx-paginate.svg)](LICENSE) + +> Koa pagination middleware and view helpers. Maintained for [Forward Email](https://forwardemail.net) [@forwardemail](https://github.com/forwardemail). + + +## Table of Contents + +* [Install](#install) +* [Usage](#usage) +* [API](#api) + * [paginate.middleware(limit, maxLimit)](#paginatemiddlewarelimit-maxlimit) + * [paginate.href(ctx)](#paginatehrefctx) + * [paginate.hasPreviousPages](#paginatehaspreviouspages) + * [paginate.hasNextPages(ctx)](#paginatehasnextpagesctx) + * [paginate.getArrayPages(ctx)](#paginategetarraypagesctx) +* [Example](#example) +* [License](#license) -> Koa pagination middleware and view helpers. ## Install ```sh -npm install -s koa-ctx-paginate +npm install koa-ctx-paginate ``` + ## Usage > Import every method: ```js -import * as paginate from 'koa-ctx-paginate'; +const paginate = require('koa-ctx-paginate'); ``` > Import selective methods: ```js -import { middleware } from 'koa-ctx-paginate'; +const { middleware } = require('koa-ctx-paginate'); ``` + ## API ### paginate.middleware(limit, maxLimit) @@ -35,8 +53,8 @@ This middleware validates and supplies default values to `ctx.paginate.skip` (an #### Arguments -- `limit` a Number to limit results returned per page (defaults to `10`) -- `maxLimit` a Number to restrict the number of results returned to per page (defaults to `50`) – through this, users will not be able to override this limit (e.g. they can't pass `?limit=10000` and crash your server) +* `limit` a Number to limit results returned per page (defaults to `10`) +* `maxLimit` a Number to restrict the number of results returned to per page (defaults to `50`) – through this, users will not be able to override this limit (e.g. they can't pass `?limit=10000` and crash your server) ### paginate.href(ctx) @@ -60,12 +78,12 @@ Note that if you pass only one argument with a type of Object, then it will gene #### Arguments -- `ctx` (**required**) – the request object returned from Koa middleware invocation +* `ctx` (**required**) – the request object returned from Koa middleware invocation #### Returned function arguments when invoked with `ctx` -- `prev` (optional) – a Boolean to determine whether or not to increment the hyperlink returned by `1` (e.g. for "Next" page links) -- `params` (optional) – an Object of querystring parameters that will override the current querystring in `ctx.query` (note that this will also override the `page` querystring value if `page` is present as a key in the `params` object) (e.g. if you want to make a link that allows the user to change the current querystring to sort by name, you would have `params` equal to `{ sort: 'name' }`) +* `prev` (optional) – a Boolean to determine whether or not to increment the hyperlink returned by `1` (e.g. for "Next" page links) +* `params` (optional) – an Object of querystring parameters that will override the current querystring in `ctx.query` (note that this will also override the `page` querystring value if `page` is present as a key in the `params` object) (e.g. if you want to make a link that allows the user to change the current querystring to sort by name, you would have `params` equal to `{ sort: 'name' }`) ### paginate.hasPreviousPages @@ -81,11 +99,11 @@ When executed with `ctx`, it will return a function that accepts two required ar #### Arguments -- `ctx` (**required**) – the request object returned from Koa middleware invocation +* `ctx` (**required**) – the request object returned from Koa middleware invocation #### Returned function arguments when invoked with `ctx` -- `pageCount` (**required**) – a Number representing the total number of pages for the given query executed on the page +* `pageCount` (**required**) – a Number representing the total number of pages for the given query executed on the page ### paginate.getArrayPages(ctx) @@ -94,25 +112,26 @@ Get all the page urls with limit. #### Arguments -- `ctx` (**required**) – the request object returned from Koa middleware invocation +* `ctx` (**required**) – the request object returned from Koa middleware invocation #### Returned function arguments when invoked with `ctx` -- `limit` (**optional**) – Default: 3, a Number representing the total number of pages for the given query executed on the page. -- `pageCount` (**required**) – a Number representing the total number of pages for the given query executed on the page. -- `currentPage` (**required**) – a Number representing the current page. +* `limit` (**optional**) – Default: 3, a Number representing the total number of pages for the given query executed on the page. +* `pageCount` (**required**) – a Number representing the total number of pages for the given query executed on the page. +* `currentPage` (**required**) – a Number representing the current page. + ## Example ```js // # app.js -import koa from 'koa'; -import Router from 'koa-router'; -import * as paginate from 'koa-ctx-paginate'; +const koa = require('koa'); +const Router = require('koa-router'); +const paginate = require('koa-ctx-paginate'); // e.g. `Users` is a database model created with Mongoose -import { Users } from '../models'; +const { Users } = require('../models'); const app = koa(); const router = new Router(); @@ -122,16 +141,12 @@ app.use(paginate.middleware(10, 50)); // let's get paginated list of users router.get('/users', async function (ctx, next) { - try { - const [ results, itemCount ] = await Promise.all([ Users.find({}).limit(ctx.query.limit).skip(ctx.paginate.skip).lean().exec(), Users.countDocuments({}) ]); - const pageCount = Math.ceil(itemCount / ctx.query.limit); - if (ctx.is('json')) { // inspired by Stripe's API response for list objects ctx.body = { @@ -147,11 +162,9 @@ router.get('/users', async function (ctx, next) { pages: paginate.getArrayPages(ctx)(3, pageCount, ctx.query.page) }); } - } catch (err) { ctx.throw(err); } - }); app.use(router.routes()); @@ -181,7 +194,7 @@ ul include _paginate ``` -> Bootstrap 4.x (used by [Lad][]): +> Bootstrap 4.x (used by \[Lad]\[]): ```pug //- _paginate.pug @@ -257,24 +270,7 @@ if paginate.hasPreviousPages || paginate.hasNextPages(pageCount) i.fa.fa-arrow-circle-right ``` -## License - -[MIT][license-url] - -[npm-image]: https://img.shields.io/npm/v/koa-ctx-paginate.svg?style=flat - -[npm-url]: https://npmjs.org/package/koa-ctx-paginate - -[downloads-image]: http://img.shields.io/npm/dm/koa-ctx-paginate.svg?style=flat -[downloads-url]: https://npmjs.org/package/koa-ctx-paginate - -[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat - -[license-url]: LICENSE - -[slack-url]: https://join.slack.com/t/ladjs/shared_invite/zt-fqei6z11-Bq2trhwHQxVc5x~ifiZG0g/ - -[slack-image]: https://img.shields.io/badge/chat-join%20slack-brightgreen +## License -[lad]: https://lad.js.org +[MIT](LICENSE) © Forward Email LLC diff --git a/index.js b/index.js new file mode 100644 index 0000000..8bc68af --- /dev/null +++ b/index.js @@ -0,0 +1,143 @@ +const querystring = require('node:querystring'); + +// +function isPlainObject(value) { + if (typeof value !== 'object' || value === null) return false; + + if (Object.prototype.toString.call(value) !== '[object Object]') return false; + + const proto = Object.getPrototypeOf(value); + if (proto === null) return true; + + const Ctor = + Object.prototype.hasOwnProperty.call(proto, 'constructor') && + proto.constructor; + return ( + typeof Ctor === 'function' && + Ctor instanceof Ctor && + Function.prototype.call(Ctor) === Function.prototype.call(value) + ); +} + +function href(ctx) { + return function (prev, params) { + const query = structuredClone(ctx.query); + + // allow overriding querystring params + // (useful for sorting and filtering) + if (isPlainObject(prev)) { + params = prev; + prev = false; + } else { + prev = typeof prev === 'boolean' ? prev : false; + query.page = prev ? (query.page -= 1) : (query.page += 1); + query.page = query.page < 1 ? 1 : query.page; + } + + if (isPlainObject(params)) Object.assign(query, params); + + const url = new URL(ctx.href); + // NOTE: we don't support existing `url.searchParams` right now + url.search = `?${querystring.stringify(query)}`; + return url.toString(); + }; +} + +function hasNextPages(ctx) { + return function (pageCount) { + if (typeof pageCount !== 'number' || pageCount < 0) + throw new Error('koa-ctx-paginate: `pageCount` is not a number >= 0'); + return ctx.query.page < pageCount; + }; +} + +function getArrayPages(ctx) { + return function (limit, pageCount, currentPage) { + // limit default is 3 + limit = limit || 3; + + if (typeof limit !== 'number' || limit < 0) + throw new Error('koa-ctx-paginate: `limit` is not a number >= 0'); + + if (typeof pageCount !== 'number' || pageCount < 0) + throw new Error('koa-ctx-paginate: `pageCount` is not a number >= 0'); + + if (typeof currentPage !== 'number' || currentPage < 0) + throw new Error('koa-ctx-paginate: `currentPage` is not a number >= 0'); + + if (limit > 0) { + const end = Math.min( + Math.max(currentPage + Math.floor(limit / 2), limit), + pageCount + ); + const start = Math.max(1, currentPage < limit - 1 ? 1 : end - limit + 1); + const pages = []; + for (let i = start; i <= end; i++) { + pages.push({ + number: i, + url: href(ctx)().replace(`page=${currentPage + 1}`, `page=${i}`) + }); + } + + return pages; + } + }; +} + +function middleware(limit, maxLimit) { + const _limit = typeof limit === 'number' ? Number.parseInt(limit, 10) : 10; + + const _maxLimit = + typeof maxLimit === 'number' ? Number.parseInt(maxLimit, 10) : 50; + + return function (ctx, next) { + ctx.query.page = + typeof ctx.query.page === 'string' + ? Number.parseInt(ctx.query.page, 10) || 1 + : typeof ctx.query.page === 'number' && + Number.isFinite(ctx.query.page) && + ctx.query.page >= 1 + ? ctx.query.page + : 1; + + ctx.query.limit = + typeof ctx.query.limit === 'string' + ? Number.parseInt(ctx.query.limit, 10) || + (typeof ctx.query.limit === 'number' && + Number.isFinite(ctx.query.limit) && + ctx.query.limit >= 0) + ? ctx.query.limit + : 0 + : _limit; + + if (ctx.query.limit > _maxLimit) ctx.query.limit = _maxLimit; + + if (ctx.query.page < 1) ctx.query.page = 1; + + if (ctx.query.limit < 0) ctx.query.limit = 0; + + const skip = ctx.query.page * ctx.query.limit - ctx.query.limit; + + ctx.paginate = { + skip, + offset: skip + }; + + ctx.state.paginate = {}; + ctx.state.paginate.page = ctx.query.page; + ctx.state.paginate.limit = ctx.query.limit; + ctx.state.paginate.href = href(ctx); + ctx.state.paginate.hasPreviousPages = ctx.query.page > 1; + ctx.state.paginate.hasNextPages = hasNextPages(ctx); + ctx.state.paginate.getArrayPages = getArrayPages(ctx); + + return next(); + }; +} + +module.exports = { + href, + hasNextPages, + getArrayPages, + middleware +}; diff --git a/package.json b/package.json index 41cca15..c0d0d24 100644 --- a/package.json +++ b/package.json @@ -2,24 +2,35 @@ "name": "koa-ctx-paginate", "description": "Koa pagination middleware and view helpers", "version": "0.0.6", - "author": "Nick Baugh ", + "author": "Forward Email LLC", "bugs": { "url": "https://github.com/koajs/ctx-paginate/issues" }, - "dependencies": { - "lodash.assign": "^4.2.0", - "lodash.clone": "^4.5.0", - "lodash.isobject": "^3.0.2", - "querystring": "^0.2.0" - }, + "contributors": [ + "Forward Email (https://forwardemail.net)" + ], + "dependencies": {}, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-preset-crocodile": "^1.0.0", - "eslint-config-crocodile": "^1.0.0" + "@commitlint/cli": "^19.3.0", + "@commitlint/config-conventional": "^19.2.2", + "ava": "^5.3.1", + "cross-env": "^7.0.3", + "eslint": "^8.55.0", + "eslint-config-xo-lass": "^2.0.1", + "fixpack": "^4.0.0", + "husky": "^8.0.3", + "lint-staged": "^15.2.7", + "nyc": "^15.1.0", + "remark-cli": "11", + "remark-preset-github": "^4.0.4", + "xo": "^0.56.0" }, "engines": { - "node": ">= 6.x" + "node": ">= 16" }, + "files": [ + "index.js" + ], "homepage": "https://github.com/koajs/ctx-paginate", "keywords": [ "better", @@ -32,16 +43,16 @@ "pagination" ], "license": "MIT", - "main": "lib/index.js", + "main": "index.js", "repository": { "type": "git", "url": "git://github.com/koajs/ctx-paginate.git" }, "scripts": { - "compile": "rm -rf lib/ && babel -d lib src", - "lint": "eslint .", - "mocha": "NODE_ENV=test node_modules/.bin/_mocha", - "prepublish": "npm run test", - "test": "npm run lint && npm run compile" + "lint": "xo --fix && remark . -qfo && fixpack", + "prepare": "husky install", + "pretest": "npm run lint", + "test": "npm run test-coverage", + "test-coverage": "cross-env NODE_ENV=test nyc ava" } } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index d8ed044..0000000 --- a/src/index.js +++ /dev/null @@ -1,126 +0,0 @@ - -// koa-ctx-paginate -// Copyright (c) 2016- Nick Baugh (http://niftylettuce.com) -// MIT Licensed - -// Koa pagination middleware and view helpers. - -// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce) -// * Source: - -import querystring from 'querystring'; -import url from 'url'; -import assign from 'lodash.assign'; -import clone from 'lodash.clone'; -import isObject from 'lodash.isobject'; - -export function href(ctx) { - - return function (prev, params) { - - let query = clone(ctx.query); - - if (typeof prev === 'object') { - params = prev; - prev = false; - } else { - prev = (typeof prev === 'boolean') ? prev : false; - query.page = prev ? query.page -= 1 : query.page += 1; - query.page = (query.page < 1) ? 1 : query.page; - } - - // allow overriding querystring params - // (useful for sorting and filtering) - // another alias for `_.assign` is `_.extend` - if (isObject(params)) - query = assign(query, params); - - return `${url.parse(ctx.originalUrl).pathname}?${querystring.stringify(query)}`; - - }; - -} - -export function hasNextPages(ctx) { - return function (pageCount) { - if (typeof pageCount !== 'number' || pageCount < 0) - throw new Error('koa-ctx-paginate: `pageCount` is not a number >= 0'); - return ctx.query.page < pageCount; - }; -} - -export function getArrayPages(ctx) { - return function (limit, pageCount, currentPage) { - - // limit default is 3 - limit = limit || 3; - - if (typeof limit !== 'number' || limit < 0) - throw new Error('koa-ctx-paginate: `limit` is not a number >= 0'); - - if (typeof pageCount !== 'number' || pageCount < 0) - throw new Error('koa-ctx-paginate: `pageCount` is not a number >= 0'); - - if (typeof currentPage !== 'number' || currentPage < 0) - throw new Error('koa-ctx-paginate: `currentPage` is not a number >= 0'); - - if (limit > 0) { - const end = Math.min(Math.max(currentPage + Math.floor(limit / 2), limit), pageCount); - const start = Math.max(1, (currentPage < (limit - 1)) ? 1 : (end - limit) + 1); - const pages = []; - for (let i = start; i <= end; i++) { - pages.push({ - number: i, - url: exports.href(ctx)().replace(`page=${(currentPage + 1)}`, `page=${i}`) - }); - } - return pages; - } - - }; - -} - -export function middleware(limit, maxLimit) { - - const _limit = (typeof limit === 'number') ? parseInt(limit, 10) : 10; - - const _maxLimit = (typeof maxLimit === 'number') ? parseInt(maxLimit, 10) : 50; - - return function _middleware(ctx, next) { - - ctx.query.page = (typeof ctx.query.page === 'string') ? - parseInt(ctx.query.page, 10) || 1 : 1; - - ctx.query.limit = (typeof ctx.query.limit === 'string') ? - parseInt(ctx.query.limit, 10) || 0 : _limit; - - if (ctx.query.limit > _maxLimit) - ctx.query.limit = _maxLimit; - - if (ctx.query.page < 1) - ctx.query.page = 1; - - if (ctx.query.limit < 0) - ctx.query.limit = 0; - - const skip = (ctx.query.page * ctx.query.limit) - ctx.query.limit; - - ctx.paginate = { - skip, - offset: skip - }; - - ctx.state.paginate = {}; - ctx.state.paginate.page = ctx.query.page; - ctx.state.paginate.limit = ctx.query.limit; - ctx.state.paginate.href = exports.href(ctx); - ctx.state.paginate.hasPreviousPages = ctx.query.page > 1; - ctx.state.paginate.hasNextPages = exports.hasNextPages(ctx); - ctx.state.paginate.getArrayPages = exports.getArrayPages(ctx); - - return next(); - - }; - -} diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..ca70b00 --- /dev/null +++ b/test/test.js @@ -0,0 +1,27 @@ +const test = require('ava'); +const paginate = require('..'); + +test('exports functions', (t) => { + t.true(typeof paginate === 'object'); + t.true(typeof paginate.href === 'function'); + t.true(typeof paginate.hasNextPages === 'function'); + t.true(typeof paginate.middleware === 'function'); +}); + +test('href', (t) => { + const ctx = { + query: { + foo: 'bar', + baz: 'boop', + limit: 1, + page: 2 + }, + href: 'https://example.com/some/page?foo=bar&limit=1&page=2' + }; + + const prev = paginate.href(ctx)(true); + t.is(prev, 'https://example.com/some/page?foo=bar&baz=boop&limit=1&page=1'); + + const next = paginate.href(ctx)(); + t.is(next, 'https://example.com/some/page?foo=bar&baz=boop&limit=1&page=3'); +});