Implement pagination logic in core api

This commit is contained in:
Alexandre Bodin 2021-08-31 16:26:01 +02:00
parent b44a552eee
commit b781213b01
4 changed files with 31 additions and 55 deletions

View File

@ -1,7 +1,7 @@
'use strict';
const _ = require('lodash');
const { createService, getFetchParams } = require('../service');
const { createService } = require('../service');
const maxLimit = 50;
const defaultLimit = 20;
@ -82,7 +82,7 @@ describe('Default Service', () => {
await service.createOrUpdate(input);
expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', {
params: { publicationState: 'live', pagination: { limit: defaultLimit } },
params: { publicationState: 'live' },
});
expect(strapi.entityService.create).toHaveBeenCalledWith('testModel', { data: input });
@ -111,7 +111,7 @@ describe('Default Service', () => {
expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', {
populate: undefined,
params: { publicationState: 'live', pagination: { limit: defaultLimit } },
params: { publicationState: 'live' },
});
expect(strapi.entityService.update).toHaveBeenCalledWith('testModel', 1, {
@ -138,7 +138,7 @@ describe('Default Service', () => {
expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', {
populate: undefined,
params: { publicationState: 'live', pagination: { limit: defaultLimit } },
params: { publicationState: 'live' },
});
expect(strapi.entityService.delete).toHaveBeenCalledWith('testModel', 1);
@ -146,36 +146,3 @@ describe('Default Service', () => {
});
});
});
describe('getFetchParams', () => {
test.each([
[`0 if limit is '0'`, { limit: '0', maxLimit }, 0],
['0 if limit is 0', { limit: 0, maxLimit }, 0],
[`0 if limit is ''`, { limit: '', maxLimit }, 0],
[`1 if limit is '1'`, { limit: '1', maxLimit }, 1],
[
`${maxLimit} if limit(500) exceeds max allowed limit (${maxLimit})`,
{ limit: '500', maxLimit },
maxLimit,
],
[
`${maxLimit} if limit is set to -1 and max allowed limit is set (${maxLimit})`,
{ limit: '-1', maxLimit },
maxLimit,
],
[`${defaultLimit} (default) if no limit is provided`, { maxLimit }, defaultLimit],
[
`${defaultLimit} (default) if limit is undefined`,
{ limit: undefined, maxLimit },
defaultLimit,
],
['1000 if limit=1000 and no max allowed limit is set', { limit: 1000 }, 1000],
])('Sets limit parameter to %s', (description, input, expected) => {
strapi.config.api.rest.maxLimit = input.maxLimit;
expect(getFetchParams({ pagination: { limit: input.limit } })).toMatchObject({
pagination: {
limit: expected,
},
});
});
});

View File

@ -8,10 +8,10 @@ const {
} = require('@strapi/utils').contentTypes;
const {
applyDefaultPagination,
getPaginationInfo,
convertPagedToStartLimit,
shouldCount,
formatPaginationResponse,
transformPaginationResponse,
} = require('./pagination');
const setPublishedAt = data => {
@ -31,7 +31,7 @@ const createCollectionTypeService = ({ model, strapi, utils }) => {
async find(opts = {}) {
const params = getFetchParams(opts.params);
const paginationInfo = applyDefaultPagination(params);
const paginationInfo = getPaginationInfo(params);
const results = await strapi.entityService.find(uid, {
params: { ...params, ...convertPagedToStartLimit(paginationInfo) },
@ -44,7 +44,7 @@ const createCollectionTypeService = ({ model, strapi, utils }) => {
return {
results,
pagination: formatPaginationResponse(paginationInfo, count),
pagination: transformPaginationResponse(paginationInfo, count),
};
}

View File

@ -1,14 +1,15 @@
'use strict';
const _ = require('lodash');
const { has, toNumber, isUndefined, isPlainObject } = require('lodash/fp');
/**
* Default limit values from config
* @return {{maxLimit: number, defaultLimit: number}}
*/
const getLimitConfigDefaults = () => ({
defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 25)),
maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null,
defaultLimit: toNumber(strapi.config.get('api.rest.defaultLimit', 25)),
maxLimit: toNumber(strapi.config.get('api.rest.maxLimit')) || null,
});
/**
@ -33,10 +34,13 @@ const shouldCount = params => {
return Boolean(strapi.config.get('api.rest.withCount', true));
};
const applyDefaultPagination = params => {
const isOffsetPagination = pagination => has('start', pagination) || has('limit', pagination);
const isPagedPagination = pagination => has('page', pagination) || has('page', pagination);
const getPaginationInfo = params => {
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
if (_.isUndefined(params.pagination) || !_.isPlainObject(params.pagination)) {
if (isUndefined(params.pagination) || !isPlainObject(params.pagination)) {
return {
start: 0,
limit: defaultLimit,
@ -45,23 +49,27 @@ const applyDefaultPagination = params => {
const { pagination } = params;
if (!_.isUndefined(pagination.pageSize) || !_.isUndefined(pagination.page)) {
const pageSize = _.isUndefined(pagination.pageSize)
if (isOffsetPagination(pagination) && isPagedPagination(pagination)) {
throw new Error('Invalid pagination parameters. Expected either start/limit or page/pageSize');
}
if (isPagedPagination(pagination)) {
const pageSize = isUndefined(pagination.pageSize)
? defaultLimit
: Math.max(1, _.toNumber(pagination.pageSize));
: Math.max(1, toNumber(pagination.pageSize));
return {
page: Math.max(1, _.toNumber(pagination.page || 1)),
page: Math.max(1, toNumber(pagination.page || 1)),
pageSize: applyMaxLimit(pageSize, maxLimit),
};
}
const limit = _.isUndefined(pagination.limit)
const limit = isUndefined(pagination.limit)
? defaultLimit
: Math.max(1, _.toNumber(pagination.limit));
: Math.max(1, toNumber(pagination.limit));
return {
start: Math.max(0, _.toNumber(pagination.start || 0)),
start: Math.max(0, toNumber(pagination.start || 0)),
limit: applyMaxLimit(limit, maxLimit),
};
};
@ -78,7 +86,7 @@ const convertPagedToStartLimit = pagination => {
return pagination;
};
const formatPaginationResponse = (paginationInfo, count) => {
const transformPaginationResponse = (paginationInfo, count) => {
if (paginationInfo.page) {
return {
...paginationInfo,
@ -94,8 +102,8 @@ const formatPaginationResponse = (paginationInfo, count) => {
};
module.exports = {
applyDefaultPagination,
getPaginationInfo,
convertPagedToStartLimit,
transformPaginationResponse,
shouldCount,
formatPaginationResponse,
};

View File

@ -61,6 +61,7 @@ module.exports = strapi => {
],
});
}
throw e;
}
});