diff --git a/src/server/router/plural.js b/src/server/router/plural.js index d8ad72f..e59228e 100644 --- a/src/server/router/plural.js +++ b/src/server/router/plural.js @@ -32,6 +32,10 @@ module.exports = function (db, name) { }) } + function getFullURL (req) { + return req.protocol + '://' + req.get('host') + req.originalUrl + } + // GET /name // GET /name?q= // GET /name?attr=&attr= @@ -156,8 +160,28 @@ module.exports = function (db, name) { _page = parseInt(_page, 10) _page = _page >= 1 ? _page : 1 _limit = parseInt(_limit, 10) || 10 - _start = (_page - 1) * _limit - chain = chain.slice(_start, _start + _limit) + var page = utils.getPage(chain.value(), _page, _limit) + var links = {} + var fullURL = getFullURL(req) + + if (page.first) { + links.first = fullURL.replace('page=' + page.current, 'page=' + page.first) + } + + if (page.prev) { + links.prev = fullURL.replace('page=' + page.current, 'page=' + page.prev) + } + + if (page.next) { + links.next = fullURL.replace('page=' + page.current, 'page=' + page.next) + } + + if (page.last) { + links.last = fullURL.replace('page=' + page.current, 'page=' + page.last) + } + + res.links(links) + chain = _.chain(page.items) } else if (_end) { _start = parseInt(_start, 10) || 0 _end = parseInt(_end, 10) diff --git a/src/server/utils.js b/src/server/utils.js index ac67050..079d67e 100644 --- a/src/server/utils.js +++ b/src/server/utils.js @@ -1,5 +1,6 @@ module.exports = { - toNative: toNative + toNative: toNative, + getPage: getPage } // Turns string to native. @@ -22,3 +23,30 @@ function toNative (value) { } return value } + +function getPage (array, page, perPage) { + var obj = {} + var start = (page - 1) * perPage + var end = page * perPage + + obj.items = array.slice(start, end) + if (obj.items.length === 0) { + return obj + } + + if (page > 1) { + obj.prev = page - 1 + } + + if (end < array.length) { + obj.next = page + 1 + } + + if (obj.items.length !== array.length) { + obj.current = page + obj.first = 1 + obj.last = Math.ceil(array.length / perPage) + } + + return obj +} \ No newline at end of file diff --git a/test/server/plural.js b/test/server/plural.js index 204f48b..5ba34db 100644 --- a/test/server/plural.js +++ b/test/server/plural.js @@ -270,8 +270,17 @@ describe('Server', function () { it('should paginate with a custom limit', function (done) { request(server) .get('/list?_page=2&_limit=1') + .set('host', 'localhost') .expect('Content-Type', /json/) .expect('x-total-count', db.list.length.toString()) + .expect('link', + [ + '; rel="first"', + '; rel="prev"', + '; rel="next"', + '; rel="last"' + ].join(', ') + ) .expect('Access-Control-Expose-Headers', 'X-Total-Count') .expect(db.list.slice(1, 2)) .expect(200, done) diff --git a/test/server/utils.js b/test/server/utils.js index ac82133..4036f58 100644 --- a/test/server/utils.js +++ b/test/server/utils.js @@ -21,4 +21,76 @@ describe('utils', function () { assert.strictEqual(utils.toNative(true), true) }) }) + + describe('getPage', function () { + var array = [1, 2, 3, 4, 5] + var perPage = 2 + + it('should return first page', function () { + assert.deepEqual( + utils.getPage(array, 1, perPage), + { + items: [1, 2], + current: 1, + first: 1, + next: 2, + last: 3 + } + ) + }) + + it('should return second page', function () { + assert.deepEqual( + utils.getPage(array, 2, perPage), + { + items: [3, 4], + current: 2, + first: 1, + prev: 1, + next: 3, + last: 3 + } + ) + }) + + it('should return third page (last)', function () { + assert.deepEqual( + utils.getPage(array, 3, perPage), + { + items: [5], + current: 3, + first: 1, + prev: 2, + last: 3 + } + ) + }) + + it('should return an empty array if page is greater than the last page', function () { + assert.deepEqual( + utils.getPage(array, 99, perPage), + { + items: [] + } + ) + }) + + it('should return the array if perPage is greater than the array size', function () { + assert.deepEqual( + utils.getPage(array, 1, 99), + { + items: array + } + ) + }) + + it('should return an empty array if the array is empty', function () { + assert.deepEqual( + utils.getPage([], 1, 1), + { + items: [] + } + ) + }) + }) })