Skip to content

Commit

Permalink
Merge 28c352b into abf3fd7
Browse files Browse the repository at this point in the history
  • Loading branch information
kjellmorten committed Apr 5, 2018
2 parents abf3fd7 + 28c352b commit 20d6290
Show file tree
Hide file tree
Showing 11 changed files with 1,051 additions and 156 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ The query object will look like this, for a request for items of type `entry`:
}
```

When the `pageSize` param is set in a request, it is taken as the max number of
documents to return in the response. When nothing else is specified, the first
page of documents is returned, and the `paging.next` prop on the response will
hold a params object that may be used to get the next page.

**Note 1:** This adapter is currently updating and deleting arrays of documents
by calling `updateOne` and `deleteOne` for every item in the array. This is not
the best method of doing it, so stay tuned for improvements.
Expand Down
143 changes: 143 additions & 0 deletions lib/adapter/createPaging-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import test from 'ava'

import createPaging from './createPaging'

// Helpers

const prepareData = (data) => data.map((item) => ({...item, _id: `${item.type}:${item.id}`}))

// Tests

test('should return next: null when no data', (t) => {
const data = []
const params = {type: 'entry', pageSize: 2}
const expected = {next: null}

const ret = createPaging(data, params)

t.deepEqual(ret, expected)
})

test('should return paging for first page', (t) => {
const data = prepareData([{id: 'ent1', type: 'entry'}, {id: 'ent2', type: 'entry'}])
const params = {
type: 'entry',
pageSize: 2
}
const expected = {
next: {
type: 'entry',
query: {_id: {$gte: 'entry:ent2'}},
pageAfter: 'entry:ent2',
pageSize: 2
}
}

const ret = createPaging(data, params)

t.deepEqual(ret, expected)
})

test('should return paging for second page', (t) => {
const data = prepareData([{id: 'ent3', type: 'entry'}, {id: 'ent4', type: 'entry'}])
const params = {
type: 'entry',
query: {_id: {$gte: 'entry:ent2'}},
pageAfter: 'entry:ent2',
pageSize: 2
}
const expected = {
next: {
type: 'entry',
query: {_id: {$gte: 'entry:ent4'}},
pageAfter: 'entry:ent4',
pageSize: 2
}
}

const ret = createPaging(data, params)

t.deepEqual(ret, expected)
})

test('should return paging when sorting', (t) => {
const data = prepareData([
{id: 'ent2', type: 'entry', attributes: {index: 1}},
{id: 'ent3', type: 'entry', attributes: {index: 2}}
])
const params = {
type: 'entry',
pageSize: 2
}
const sort = {
'attributes.index': 1
}
const expected = {
next: {
type: 'entry',
query: {'attributes.index': {$gte: 2}},
pageAfter: 'entry:ent3',
pageSize: 2
}
}

const ret = createPaging(data, params, sort)

t.deepEqual(ret, expected)
})

test('should return paging when sorting descending', (t) => {
const data = prepareData([
{id: 'ent3', type: 'entry', attributes: {index: 2}},
{id: 'ent2', type: 'entry', attributes: {index: 1}}
])
const params = {
type: 'entry',
pageSize: 2
}
const sort = {
'attributes.index': -1
}
const expected = {
next: {
type: 'entry',
query: {'attributes.index': {$lte: 1}},
pageAfter: 'entry:ent2',
pageSize: 2
}
}

const ret = createPaging(data, params, sort)

t.deepEqual(ret, expected)
})

test('should return paging when sorting ascending and descending', (t) => {
const data = prepareData([
{id: 'ent3', type: 'entry', attributes: {index: 2}},
{id: 'ent2', type: 'entry', attributes: {index: 1}}
])
const params = {
type: 'entry',
pageSize: 2
}
const sort = {
'attributes.index': -1,
id: 1
}
const expected = {
next: {
type: 'entry',
query: {
'attributes.index': {$lte: 1},
id: {$gte: 'ent2'}
},
pageAfter: 'entry:ent2',
pageSize: 2
}
}

const ret = createPaging(data, params, sort)

t.deepEqual(ret, expected)
})
35 changes: 35 additions & 0 deletions lib/adapter/createPaging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const dotprop = require('dot-prop')

const createQuery = (lastItem, sort) => {
if (sort) {
return Object.keys(sort).reduce((query, key) => {
const value = dotprop.get(lastItem, key)
const operator = (sort[key] > 0) ? '$gte' : '$lte'
return {...query, [key]: {[operator]: value}}
}, {})
} else {
return {_id: {$gte: lastItem._id}}
}
}

const createPaging = (data, params, sort) => {
if (data.length === 0) {
return {next: null}
}
const lastItem = data[data.length - 1]

const {typePlural, ...nextParams} = params

const query = createQuery(lastItem, sort)

return {
next: {
...nextParams,
pageSize: params.pageSize,
pageAfter: lastItem._id,
query
}
}
}

module.exports = createPaging
Loading

0 comments on commit 20d6290

Please sign in to comment.