Skip to content

Commit 058dc69

Browse files
author
Srinand Balaji
authored
Merge pull request #305 from mixmaxhq/srinand/expose-encodePaginationTokens
feat: extract/expose a function to encode pagination tokens
2 parents 83979dd + 8f80382 commit 058dc69

File tree

3 files changed

+73
-17
lines changed

3 files changed

+73
-17
lines changed

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const find = require('./find');
44
const findWithReq = require('./findWithReq');
55
const search = require('./search');
66
const sanitizeQuery = require('./utils/sanitizeQuery');
7+
const { encodePaginationTokens } = require('./utils/query');
78
const mongoosePlugin = require('./mongoose.plugin');
89

910
module.exports = {
@@ -14,4 +15,5 @@ module.exports = {
1415
search,
1516
mongoosePlugin,
1617
sanitizeQuery,
18+
encodePaginationTokens,
1719
};

src/utils/query.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
11
const bsonUrlEncoding = require('./bsonUrlEncoding');
22
const objectPath = require('object-path');
33

4+
/**
5+
* Helper function to encode pagination tokens.
6+
*
7+
* NOTE: this function modifies the passed-in `response` argument directly.
8+
*
9+
* @param {Object} params
10+
* * @param {String} paginatedField
11+
* @param {Object} response The response
12+
* @param {String?} previous
13+
* @param {String?} next
14+
*
15+
* @returns void
16+
*/
17+
function encodePaginationTokens(params, response) {
18+
const shouldSecondarySortOnId = params.paginatedField !== '_id';
19+
20+
if (response.previous) {
21+
const previousPaginatedField = objectPath.get(response.previous, params.paginatedField);
22+
if (shouldSecondarySortOnId) {
23+
response.previous = bsonUrlEncoding.encode([previousPaginatedField, response.previous._id]);
24+
} else {
25+
response.previous = bsonUrlEncoding.encode(previousPaginatedField);
26+
}
27+
}
28+
if (response.next) {
29+
const nextPaginatedField = objectPath.get(response.next, params.paginatedField);
30+
if (shouldSecondarySortOnId) {
31+
response.next = bsonUrlEncoding.encode([nextPaginatedField, response.next._id]);
32+
} else {
33+
response.next = bsonUrlEncoding.encode(nextPaginatedField);
34+
}
35+
}
36+
}
37+
438
module.exports = {
539
/**
640
* Parses the raw results from a find or aggregate query and generates a response object that
@@ -13,7 +47,6 @@ module.exports = {
1347
*/
1448
prepareResponse(results, params) {
1549
const hasMore = results.length > params.limit;
16-
const shouldSecondarySortOnId = params.paginatedField !== '_id';
1750
// Remove the extra element that we added to 'peek' to see if there were more entries.
1851
if (hasMore) results.pop();
1952

@@ -31,26 +64,13 @@ module.exports = {
3164
hasNext,
3265
};
3366

34-
if (response.previous) {
35-
const previousPaginatedField = objectPath.get(response.previous, params.paginatedField);
36-
if (shouldSecondarySortOnId) {
37-
response.previous = bsonUrlEncoding.encode([previousPaginatedField, response.previous._id]);
38-
} else {
39-
response.previous = bsonUrlEncoding.encode(previousPaginatedField);
40-
}
41-
}
42-
if (response.next) {
43-
const nextPaginatedField = objectPath.get(response.next, params.paginatedField);
44-
if (shouldSecondarySortOnId) {
45-
response.next = bsonUrlEncoding.encode([nextPaginatedField, response.next._id]);
46-
} else {
47-
response.next = bsonUrlEncoding.encode(nextPaginatedField);
48-
}
49-
}
67+
encodePaginationTokens(params, response);
5068

5169
return response;
5270
},
5371

72+
encodePaginationTokens,
73+
5474
/**
5575
* Generates a `$sort` object given the parameters
5676
*

test/utils/query.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const bsonUrlEncoding = require('../../src/utils/bsonUrlEncoding');
2+
const { encodePaginationTokens } = require('../../src/utils/query');
3+
4+
describe('encodePaginationTokens', () => {
5+
it('encodes the pagination tokens on the passed-in response object', () => {
6+
const params = {
7+
paginatedField: '_id',
8+
};
9+
const response = {
10+
next: { _id: '789' },
11+
previous: { _id: '456' },
12+
};
13+
14+
encodePaginationTokens(params, response);
15+
16+
expect(response.next).toEqual(bsonUrlEncoding.encode('789'));
17+
expect(response.previous).toEqual(bsonUrlEncoding.encode('456'));
18+
});
19+
20+
it("constructs pagination tokens using both the _id and the paginatedField if the latter isn't the former", () => {
21+
const params = {
22+
paginatedField: 'name',
23+
};
24+
const response = {
25+
next: { _id: '789', name: 'Test 2' },
26+
previous: { _id: '456', name: 'Test' },
27+
};
28+
29+
encodePaginationTokens(params, response);
30+
31+
expect(response.next).toEqual(bsonUrlEncoding.encode(['Test 2', '789']));
32+
expect(response.previous).toEqual(bsonUrlEncoding.encode(['Test', '456']));
33+
});
34+
});

0 commit comments

Comments
 (0)