restify-paginate
Advanced tools
Comparing version 0.0.2 to 0.0.3
85
index.js
@@ -19,4 +19,4 @@ var extend = require('extend'); | ||
req.paginate = { | ||
page: req.params[opts.paramsNames.page] || defaults.defaults.page, | ||
per_page: req.params[opts.paramsNames.per_page] || defaults.defaults.per_page, | ||
page: parseInt(req.params[opts.paramsNames.page]) || defaults.defaults.page, | ||
per_page: parseInt(req.params[opts.paramsNames.per_page]) || defaults.defaults.per_page, | ||
}; | ||
@@ -51,4 +51,4 @@ | ||
* Generates the first, prev, next, last links | ||
* @param {Integer} count The total number of elements to paginate | ||
* @return {Object} A Hash like object with the links name as key and links as values | ||
* @param {Integer} [count] The total number of elements to paginate. If no count is provided, no last page is added | ||
* @return {Object} A Hash like object with the links name as key and links as values | ||
*/ | ||
@@ -60,10 +60,13 @@ paginate.getLinks = function (count) { | ||
// The current page is not the first one so we generate the first and prev links | ||
if (parseInt(page) !== defaults.defaults.page) { | ||
links.prev = parseInt(page) - 1; | ||
if (page !== defaults.defaults.page) { | ||
links.prev = page - 1; | ||
links.first = defaults.defaults.page; | ||
} | ||
if ((page) * per_page < count) { | ||
if (count !== undefined && page * per_page < count) { | ||
links.last = Math.floor(count / per_page) + defaults.defaults.page; | ||
links.next = parseInt(page) + 1; | ||
} | ||
if (count === undefined || page * per_page < count) { | ||
links.next = page + 1; | ||
} | ||
return links; | ||
@@ -73,16 +76,15 @@ } | ||
// The current page is not the first one so we generate the first and prev links | ||
if (parseInt(page) !== defaults.defaults.page) { | ||
if (page !== defaults.defaults.page) { | ||
params.page = defaults.defaults.page; | ||
links.first = baseUrl + server.router.render(req.route.name, params, params); | ||
params.page = parseInt(page) - 1; | ||
params.page = page - 1; | ||
links.prev = baseUrl + server.router.render(req.route.name, params, params); | ||
} | ||
if ((page) * per_page < count) { | ||
if (count !== undefined && page * per_page < count) { | ||
params.page = count % per_page === 0 ? count / per_page : Math.floor(count / per_page + defaults.defaults.page); | ||
links.last = baseUrl + server.router.render(req.route.name, params, params); | ||
params.page = parseInt(page) + 1; | ||
} | ||
if (count === undefined || page * per_page < count) { | ||
params.page = page + 1; | ||
links.next = baseUrl + server.router.render(req.route.name, params, params); | ||
@@ -105,2 +107,55 @@ } | ||
}; | ||
/** | ||
* Generates a response, containing the given data and links to the other pages | ||
* @param {Array<Object>} data an array of Objects | ||
* @param {Integer} [count] the total count of data. If count is not provided, the link to the last page won't be generated | ||
* @return {Object} an Object containing the data, and links to the other pages | ||
*/ | ||
paginate.getResponse = function (data, count) { | ||
return { | ||
data: data, | ||
pages: res.paginate.getLinks(count) | ||
}; | ||
}; | ||
/** | ||
* Generates a paginated response. The data will be paginated, and links to the other pages will be generated | ||
* @param {Array<Object>} an array of Objects, to be paginated | ||
* @return {Object} an Object containing the paginated data, and links to the other pages | ||
*/ | ||
paginate.getPaginatedResponse = function (data, count) { | ||
var index = (page - 1) * per_page; | ||
if(data.length < index - per_page || page <= 0) { | ||
return { | ||
error: 'page ' + page + ' not found' | ||
}; | ||
} | ||
return paginate.getResponse(data.slice(index, index + per_page), data.length); | ||
}; | ||
/** | ||
* Sends a response, generated by the getResponse() method | ||
* @param {Array<Object>} data an array of Objects, to be paginated | ||
* @param {Integer} [count] the total count of data. If count is not provided, the link to the last page won't be generated | ||
*/ | ||
paginate.send = function (data, count) { | ||
res.send(paginate.getResponse(data, count)); | ||
}; | ||
/** | ||
* Sends a paginated response, generated by the getPaginatedResponse() method | ||
* @param {Array<Object>} data an array of Objects, to be paginated | ||
*/ | ||
paginate.sendPaginated = function (data) { | ||
var paginatedResponse = paginate.getPaginatedResponse(data); | ||
if(paginatedResponse.error) { | ||
res.status(404); | ||
} | ||
res.send(paginatedResponse); | ||
}; | ||
res.paginate = paginate; | ||
@@ -107,0 +162,0 @@ next(); |
{ | ||
"name": "restify-paginate", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "A resitfy a middleware that helps the navigation between pages.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
160
README.md
@@ -59,17 +59,113 @@ # restify-paginate | ||
So now you can use this information to make your database query | ||
It will also add a `paginate` object to the response object, which contains methods for creating paginated responses. | ||
###Paginated responses | ||
with this information, restify-paginate can generate paginated reponses for you. There basically are just two methods you need, depending on what you're working with. | ||
####Generating a response from a full dataset | ||
If you working with a full dataset you want to paginate, you can use the `getPaginatedResponse(data)` method. This will take a whole dataset and create a response object which contains `data` and `pages` linking to the other pages. E.g.: | ||
```js | ||
// SQL like query | ||
var query = 'SELECT * FROM my_table' | ||
+ 'OFFSET ' + (req.paginate.page * req.paginate.per_page) | ||
+ ' LIMIT ' + req.params.per_page; | ||
// Mongoose like query | ||
Potatoes.find() | ||
.offset(req.paginate.page * req.paginate.per_page) | ||
.limit(req.params.per_page); | ||
// example data | ||
var data = { | ||
first: 1, | ||
second: 2, | ||
third: 3, | ||
// and so on ... | ||
fortytwothousand: 42000 | ||
} | ||
// Let's say page is set to 2 and per_page to 4. Calling | ||
var paginatedResponse = res.paginate.getPaginatedResponse(data); | ||
console.log(paginatedResponse); | ||
// will now print: | ||
{ | ||
data: { | ||
five: 5, | ||
six: 6, | ||
seven: 7, | ||
eight: 8 | ||
}, | ||
pages: { | ||
prev: 'http://api.myurl.com/myresource?page=1&per_page=4', | ||
next: 'http://api.myurl.com/myresource?page=3&per_page=4', | ||
first: 'http://api.myurl.com/myresource?page=1&per_page=4', | ||
last: 'http://api.myurl.com/myresource?page=8399&per_page=4', | ||
} | ||
} | ||
// now send the paginated response | ||
res.send(paginatedResponse); | ||
``` | ||
It will also add a `paginate` object in the response object that contains two functions that can be used to either get the pages links or add them to the response headers. | ||
since you usually will send() a paginated response after generating it, there is a shortcut method for that: | ||
```js | ||
// generates a paginated response and calls send(response) | ||
res.paginate.sendPaginatedResponse(data); | ||
``` | ||
####Generating a response with a already paginated dataset | ||
If you want to paginate data from a database, you probably want to paginate your data by using `offset` and `limit`, instead of retrieving the whole dataset and using `sendPaginatedResponse()`. This is where the `req.paginate.page` and `req.paginate.per_page` come in handy. | ||
```js | ||
// SQL like query | ||
var query = 'SELECT * FROM my_table' | ||
+ 'OFFSET ' + (req.paginate.page * req.paginate.per_page) | ||
+ ' LIMIT ' + req.params.per_page; | ||
// Mongoose like query | ||
Potatoes.find() | ||
.offset(req.paginate.page * req.paginate.per_page) | ||
.limit(req.params.per_page); | ||
``` | ||
let's you return a paginated dataset from your database. Now you can generate a response containing this paginated data and links to the other pages: | ||
```js | ||
// generate a response using the data retrieved from the database | ||
var response = res.paginate.getResponse(data); | ||
// send the response | ||
res.paginate.send(paginate); | ||
``` | ||
There is a shortcut for this as well | ||
```js | ||
// generate a response and call send(response) | ||
res.paginate.send(data); | ||
``` | ||
The response generated by this, will obviously not contain a link to the last page, since there is no information on how big the whole dataset is. If you need a link to the last page, you can also generate a response providing the size of the whole dataset. | ||
```js | ||
// lets say there are 1000 items in your databse... | ||
res.paginate.send(data, 1000); | ||
``` | ||
###Creating custom paginated responses | ||
If this doesn't quite fit your needs, you can create your own responses, [using paginate-restifys methods](#functions-reference) | ||
e.g. using getLinks() | ||
```js | ||
// SQL like query | ||
var query = 'SELECT * FROM my_table' | ||
+ 'OFFSET ' + (req.paginate.page * req.paginate.per_page) | ||
+ ' LIMIT ' + req.params.per_page; | ||
// Mongoose like query | ||
Potatoes.find() | ||
.offset(req.paginate.page * req.paginate.per_page) | ||
.limit(req.params.per_page); | ||
``` | ||
You can now get your links based on the total count of your result set | ||
@@ -95,2 +191,4 @@ | ||
Depending on how you are retrieving your data, it may be the case, that you'll need to do another query to get total count of items. For huge data sets, this could have an significant performance impact. If that is the case, and you don't necessarily need the `last` page, you can call the `getLinks()` method without a param. This will only generate the first, next and previous links. | ||
## Options | ||
@@ -143,3 +241,3 @@ | ||
``` | ||
```json | ||
{ | ||
@@ -168,10 +266,10 @@ first: 1, | ||
### res.paginate.getLinks(count) | ||
### res.paginate.getLinks([count]) | ||
**params**: | ||
- count: The total number of results | ||
- count (optional): The total number of results. If count is not provided, the link to the last page won't be generated | ||
Returns an object containing the pages. | ||
### res.paginate.addLinks(count) | ||
### res.paginate.addLinks([count]) | ||
@@ -182,1 +280,35 @@ **params**: | ||
Add a `Link` header to the response that contains the pages. | ||
### res.paginate.getResponse(data, [count]) | ||
generates a reponse, containing the given data and a link to the other pages. | ||
**params**: | ||
- data: An Array of Objects | ||
- count: The total count of Items. If count is not provided, the link to the last page won't be generated | ||
Returns an object containing the data and pages | ||
### res.paginate.sendPaginated(data) | ||
sends the data generated by `getResponse` | ||
**params**: | ||
- data: An Array of Objects | ||
- count: The total count of Items. If count is not provided, the link to the last page won't be generated | ||
### res.paginate.getPaginatedResponse(data) | ||
generates a paginated response | ||
**params**: | ||
- data: An Array of Objects, which you want to paginate | ||
Returns an object containing the data and pages | ||
### res.paginate.sendPaginated(data) | ||
sends the data generated by `getPaginatedResponse | ||
**params**: | ||
- data: An Array of Objects, which you want to paginate |
@@ -86,1 +86,51 @@ var restify = require('restify'), | ||
}); | ||
describe('The paginate object added to the request object', function (done) { | ||
var testServer; | ||
before(function (done) { | ||
testServer = restify.createServer({ | ||
name: 'test' | ||
}); | ||
testServer.use(restify.queryParser()); | ||
testServer.use(paginate(testServer)); | ||
testServer.listen(9999, done); | ||
}); | ||
it('should contain a page and per_page object', function (done) { | ||
testServer.get('/object-test', function (req, res, next) { | ||
try { | ||
req.paginate.should.have.property('page'); | ||
req.paginate.should.have.property('per_page'); | ||
done(); | ||
} catch (e) { | ||
done(e); | ||
} | ||
}); | ||
request({ | ||
uri: 'http://localhost:9999/object-test' | ||
}); | ||
}); | ||
it('should cast page and per_page to number, if they\'re URL params', function (done) { | ||
testServer.get('/type-test', function (req, res, next) { | ||
try { | ||
req.paginate.page.should.be.a.Number(); | ||
req.paginate.per_page.should.be.a.Number(); | ||
done(); | ||
} catch (e) { | ||
done(e); | ||
} | ||
}); | ||
request({ | ||
uri: 'http://localhost:9999/type-test?page=2&per_page=2' | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32569
9
587
310