New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

koa-pagination

Package Overview
Dependencies
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

koa-pagination - npm Package Compare versions

Comparing version 0.0.2 to 0.1.0

.jshintignore

55

index.js

@@ -7,6 +7,6 @@

var _ = require('lodash');
var InvalidRangeError = require('./errors/invalid-range-error');
var MalformedRangeError = require('./errors/malformed-range-error');
var contentRange = require('content-range');
var parseRange = require('range-parser');
var RangeNotSatisfiableError = require('./errors/range-not-satisfiable-error');
var contentRangeFormat = require('http-content-range-format');
var rangeSpecifierParser = require('range-specifier-parser');

@@ -19,3 +19,2 @@ /**

options = _.assign({
limit: 20,
maximum: 50

@@ -25,12 +24,13 @@ }, options);

return function *paginate(next) {
// Ensure that `limit` is never higher than `maximum`.
var limit = options.limit > options.maximum ? options.maximum : options.limit;
var first = 0;
var last = options.maximum;
var maximum = options.maximum;
var offset = 0;
var unit = 'bytes';
// Handle `Range` header.
if (this.get('Range')) {
var range = parseRange(maximum + 1, this.get('Range'));
var range = rangeSpecifierParser(this.get('Range'));
if (range === -1) {
throw new InvalidRangeError();
throw new RangeNotSatisfiableError();
}

@@ -43,27 +43,38 @@

// Update `limit` and `offset` values.
limit = range[0].end;
offset = range[0].start;
first = range.first;
last = range.last;
unit = range.unit;
}
// Set range values on context.
// Set pagination object on context.
this.pagination = {
limit: limit,
offset: offset
limit: last + 1,
offset: first
};
// Prevent pages with more items than allowed.
if ((last - first + 1) > maximum) {
last = first + maximum - 1;
}
yield* next;
// Fix limit value if is higher than count.
if (limit > this.pagination.count) {
limit = this.pagination.count;
var length = this.pagination.length;
// Fix `last` value if `length` is lower.
if (last > length) {
last = length - 1;
}
// Set `Content-Range` based on available items.
this.set('Content-Range', contentRange.format({
count: this.pagination.count,
limit: limit,
name: 'items',
offset: this.pagination.offset
this.set('Content-Range', contentRangeFormat({
first: first,
last: last,
length: length,
unit: unit
}));
// Set the response as `Partial Content`.
this.status = 206;
};
};

13

package.json
{
"name": "koa-pagination",
"version": "0.0.2",
"version": "0.1.0",
"description": "Koa Pagination",

@@ -10,7 +10,8 @@ "main": "index.js",

"dependencies": {
"content-range": "0.2.0",
"create-error": "0.3.1",
"debug": "2.1.0",
"http-content-range-format": "1.0.0",
"lodash": "2.4.1",
"range-parser": "1.0.2"
"range-specifier-parser": "0.1.0",
"util": "0.10.3"
},

@@ -34,9 +35,5 @@ "devDependencies": {

},
"precommit": [
"forbidden-keywords",
"jshint"
],
"author": "Seegno",
"license": "MIT",
"repository": "git@github.com:seegno/koa-pagination"
"repository": "git@github.com:seegno/koa-paginate"
}
# Koa Pagination
[![Build Status](https://travis-ci.org/seegno/koa-pagination.svg?branch=master)](https://travis-ci.org/seegno/koa-pagination)
Koa Pagination is a middleware to handle [Range Pagination Headers](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) using `Range` & `Content-Range` entity-headers.
## Installation
Choose your preferred method:
* npm: `npm install --save koa-pagination`
* Download: [koa-pagination](https://github.com/seegno/koa-pagination)
### Configuration
The middleware can be configured with the following parameters:
- Maximum: Maximum number of items allowed per page (50 items by default).
You can change the defaults by doing:
```js
paginate({
maximum: 100
});
```
## Usage
```js
var koa = require('koa');
var paginate = require('koa-pagination');
var app = koa();
app.get('/', paginate(), function *() {
// `paginate` middleware will inject a `pagination` object in the `koa` context,
// which will allow you to use the `pagination.offset` and `pagination.limit`
// in your data retrieval methods.
this.body = foobar.getData({
limit: this.pagination.limit,
offset: this.pagination.offset
});
// This is needed in order to expose the length in `Content-Range` header.
this.pagination.length = foobar.count();
});
app.listen(3000);
```
### Request
You can provide the `Range` header specifying the items you want to retrieve. For instance to retrieve the first 5 elements:
```js
'Range: items=0-5'
```
### Response
This will generate a response with the following `Content-Range` header:
```js
'Content-Range: items 0-4/*'
```
The `*` will be replaced with the total number of items provided in the `length` variable.
## Running tests
```sh
npm test
```

@@ -10,2 +10,3 @@

var request = require('./request')();
var util = require('util');

@@ -19,12 +20,11 @@ chai.should();

describe('paginate', function() {
it('should accept a `limit` option', function *() {
it('should use the default values', function *() {
var app = koa();
app.use(paginate({
limit: 5
}));
app.use(paginate());
yield request(app.listen())
.get('/')
.expect('Content-Range', 'items 0-4/*')
.expect(206)
.expect('Content-Range', 'bytes 0-49/*')
.end();

@@ -42,7 +42,8 @@ });

.get('/')
.expect('Content-Range', 'items 0-2/*')
.expect(206)
.expect('Content-Range', 'bytes 0-2/*')
.end();
});
it('should set `Content-Range` headers by default', function *() {
it('should accept a `Range` header', function *() {
var app = koa();

@@ -54,7 +55,9 @@

.get('/')
.expect('Content-Range', 'items 0-19/*')
.set('Range', 'items=0-5')
.expect(206)
.expect('Content-Range', 'items 0-5/*')
.end();
});
it('should accept a `Range` header', function *() {
it('should give an error if the `Range` is malformed', function *() {
var app = koa();

@@ -66,8 +69,8 @@

.get('/')
.set('Range', 'items=0-5')
.expect('Content-Range', 'items 0-4/*')
.set('Range', 'invalid')
.expect(412, 'Precondition Failed')
.end();
});
it('should allow specifying a `count` variable in the pagination', function *() {
it('should give an error if the `Range` is invalid', function *() {
var app = koa();

@@ -77,15 +80,25 @@

app.use(function *(next) {
this.pagination.count = 10;
yield request(app.listen())
.get('/')
.set('Range', 'bytes=5-1')
.expect(416, 'Range Not Satisfiable')
.end();
});
yield* next;
});
it('should not allow `limit` value superior to `maximum`', function *() {
var app = koa();
app.use(paginate({
maximum: 3
}));
yield request(app.listen())
.get('/')
.expect('Content-Range', 'items 0-9/10')
.expect(206)
.set('Range', 'items=0-5')
.expect('Content-Range', 'items 0-2/*')
.end();
});
it('should give an error if the `Range` is malformed', function *() {
it('should not allow `limit` value superior to `length`', function *() {
var app = koa();

@@ -95,34 +108,47 @@

app.use(function *() {
this.pagination.length = 3;
});
yield request(app.listen())
.get('/')
.set('Range', 'invalid')
.expect(412, 'Precondition Failed')
.expect(206)
.set('Range', 'items=0-5')
.expect('Content-Range', 'items 0-2/3')
.end();
});
it('should give an error if the `Range` is invalid', function *() {
it('should set `limit` to `N+1` when `Range` is `items=0-N`', function *() {
var app = koa();
var n = 5;
app.use(paginate());
app.use(function *() {
this.pagination.limit.should.equal(n + 1);
});
yield request(app.listen())
.get('/')
.set('Range', 'items=5-1')
.expect(412, 'Precondition Failed')
.expect(206)
.set('Range', util.format('items=0-%s', n))
.end();
});
it('should not allow `limit` value superior to `maximum`', function *() {
it('should set `offset` to `N` when `Range` is `items=N-5`', function *() {
var app = koa();
var n = 2;
app.use(paginate({
limit: 5,
maximum: 3
}));
app.use(paginate());
app.use(function *() {
this.pagination.offset.should.equal(n);
});
yield request(app.listen())
.get('/')
.expect('Content-Range', 'items 0-2/*')
.expect(206)
.set('Range', util.format('items=%s-5', n))
.end();
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc