mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
Implement REST API pagination with paged or offset and withCount
This commit is contained in:
parent
7eaa8ae95e
commit
b44a552eee
@ -6,6 +6,7 @@ testApp/**
|
||||
examples/**
|
||||
cypress/**
|
||||
packages/generators/generators/lib/files/
|
||||
packages/generators/app/lib/resources/files/
|
||||
packages/core/helper-plugin/build/**
|
||||
packages/core/helper-plugin/lib/src/components/**
|
||||
packages/core/helper-plugin/lib/src/testUtils/**
|
||||
|
||||
7
examples/getstarted/config/api.js
Normal file
7
examples/getstarted/config/api.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
rest: {
|
||||
defaultLimit: 25,
|
||||
maxLimit: 30,
|
||||
withCount: false,
|
||||
},
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { sanitizeEntity } = require('@strapi/utils');
|
||||
const { sanitizeEntity, contentTypes } = require('@strapi/utils');
|
||||
|
||||
const { transformResponse } = require('./transform');
|
||||
const createSingleTypeController = require('./single-type');
|
||||
@ -18,7 +18,7 @@ module.exports = ({ service, model }) => {
|
||||
},
|
||||
};
|
||||
|
||||
if (model.kind === 'singleType') {
|
||||
if (contentTypes.isSingleType(model)) {
|
||||
return createSingleTypeController(ctx);
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,13 @@ const {
|
||||
constants: { PUBLISHED_AT_ATTRIBUTE },
|
||||
} = require('@strapi/utils').contentTypes;
|
||||
|
||||
const {
|
||||
applyDefaultPagination,
|
||||
convertPagedToStartLimit,
|
||||
shouldCount,
|
||||
formatPaginationResponse,
|
||||
} = require('./pagination');
|
||||
|
||||
const setPublishedAt = data => {
|
||||
data[PUBLISHED_AT_ATTRIBUTE] = propOr(new Date(), PUBLISHED_AT_ATTRIBUTE, data);
|
||||
};
|
||||
@ -21,10 +28,30 @@ const createCollectionTypeService = ({ model, strapi, utils }) => {
|
||||
const { sanitizeInput, getFetchParams } = utils;
|
||||
|
||||
return {
|
||||
find(opts = {}) {
|
||||
async find(opts = {}) {
|
||||
const params = getFetchParams(opts.params);
|
||||
|
||||
return strapi.entityService.findPage(uid, { params });
|
||||
const paginationInfo = applyDefaultPagination(params);
|
||||
|
||||
const results = await strapi.entityService.find(uid, {
|
||||
params: { ...params, ...convertPagedToStartLimit(paginationInfo) },
|
||||
});
|
||||
|
||||
if (shouldCount(params)) {
|
||||
const count = await strapi.entityService.count(uid, {
|
||||
params: { ...params, ...paginationInfo },
|
||||
});
|
||||
|
||||
return {
|
||||
results,
|
||||
pagination: formatPaginationResponse(paginationInfo, count),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
results,
|
||||
pagination: paginationInfo,
|
||||
};
|
||||
},
|
||||
|
||||
findOne(entityId, opts = {}) {
|
||||
|
||||
@ -26,54 +26,6 @@ const createService = ({ model, strapi }) => {
|
||||
return createCollectionTypeService({ model, strapi, utils });
|
||||
};
|
||||
|
||||
/**
|
||||
* Default limit values from config
|
||||
* @return {{maxLimit: number, defaultLimit: number}}
|
||||
*/
|
||||
const getLimitConfigDefaults = () => ({
|
||||
defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 100)),
|
||||
maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null,
|
||||
});
|
||||
|
||||
/**
|
||||
* if there is max limit set and limit exceeds this number, return configured max limit
|
||||
* @param {number} limit - limit you want to cap
|
||||
* @param {number?} maxLimit - maxlimit used has capping
|
||||
* @returns {number}
|
||||
*/
|
||||
const applyMaxLimit = (limit, maxLimit) => {
|
||||
if (maxLimit && (limit === -1 || limit > maxLimit)) {
|
||||
return maxLimit;
|
||||
}
|
||||
|
||||
return limit;
|
||||
};
|
||||
|
||||
const applyDefaultPagination = params => {
|
||||
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
|
||||
|
||||
if (_.isUndefined(params.pagination) || !_.isPlainObject(params.pagination)) {
|
||||
return {
|
||||
limit: defaultLimit,
|
||||
};
|
||||
}
|
||||
|
||||
const { pagination } = params;
|
||||
|
||||
if (!_.isUndefined(pagination.pageSize)) {
|
||||
return {
|
||||
page: pagination.page,
|
||||
pageSize: applyMaxLimit(_.toNumber(pagination.pageSize), maxLimit),
|
||||
};
|
||||
}
|
||||
|
||||
const limit = _.isUndefined(pagination.limit) ? defaultLimit : _.toNumber(pagination.limit);
|
||||
return {
|
||||
start: pagination.start,
|
||||
limit: applyMaxLimit(limit, maxLimit),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create default fetch params
|
||||
* @param {*} params
|
||||
@ -83,7 +35,6 @@ const getFetchParams = (params = {}) => {
|
||||
return {
|
||||
publicationState: DP_PUB_STATE_LIVE,
|
||||
...params,
|
||||
pagination: applyDefaultPagination(params),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
101
packages/core/strapi/lib/core-api/service/pagination.js
Normal file
101
packages/core/strapi/lib/core-api/service/pagination.js
Normal file
@ -0,0 +1,101 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
/**
|
||||
* 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,
|
||||
});
|
||||
|
||||
/**
|
||||
* if there is max limit set and limit exceeds this number, return configured max limit
|
||||
* @param {number} limit - limit you want to cap
|
||||
* @param {number?} maxLimit - maxlimit used has capping
|
||||
* @returns {number}
|
||||
*/
|
||||
const applyMaxLimit = (limit, maxLimit) => {
|
||||
if (maxLimit && (limit === -1 || limit > maxLimit)) {
|
||||
return maxLimit;
|
||||
}
|
||||
|
||||
return limit;
|
||||
};
|
||||
|
||||
const shouldCount = params => {
|
||||
if (_.has(params, 'pagination.withCount')) {
|
||||
return params.pagination.withCount === 'false' ? false : true;
|
||||
}
|
||||
|
||||
return Boolean(strapi.config.get('api.rest.withCount', true));
|
||||
};
|
||||
|
||||
const applyDefaultPagination = params => {
|
||||
const { defaultLimit, maxLimit } = getLimitConfigDefaults();
|
||||
|
||||
if (_.isUndefined(params.pagination) || !_.isPlainObject(params.pagination)) {
|
||||
return {
|
||||
start: 0,
|
||||
limit: defaultLimit,
|
||||
};
|
||||
}
|
||||
|
||||
const { pagination } = params;
|
||||
|
||||
if (!_.isUndefined(pagination.pageSize) || !_.isUndefined(pagination.page)) {
|
||||
const pageSize = _.isUndefined(pagination.pageSize)
|
||||
? defaultLimit
|
||||
: Math.max(1, _.toNumber(pagination.pageSize));
|
||||
|
||||
return {
|
||||
page: Math.max(1, _.toNumber(pagination.page || 1)),
|
||||
pageSize: applyMaxLimit(pageSize, maxLimit),
|
||||
};
|
||||
}
|
||||
|
||||
const limit = _.isUndefined(pagination.limit)
|
||||
? defaultLimit
|
||||
: Math.max(1, _.toNumber(pagination.limit));
|
||||
|
||||
return {
|
||||
start: Math.max(0, _.toNumber(pagination.start || 0)),
|
||||
limit: applyMaxLimit(limit, maxLimit),
|
||||
};
|
||||
};
|
||||
|
||||
const convertPagedToStartLimit = pagination => {
|
||||
if (_.has(pagination, 'page')) {
|
||||
const { page, pageSize } = pagination;
|
||||
return {
|
||||
start: (page - 1) * pageSize,
|
||||
limit: pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
return pagination;
|
||||
};
|
||||
|
||||
const formatPaginationResponse = (paginationInfo, count) => {
|
||||
if (paginationInfo.page) {
|
||||
return {
|
||||
...paginationInfo,
|
||||
pageCount: Math.ceil(count / paginationInfo.pageSize),
|
||||
total: count,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...paginationInfo,
|
||||
total: count,
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
applyDefaultPagination,
|
||||
convertPagedToStartLimit,
|
||||
shouldCount,
|
||||
formatPaginationResponse,
|
||||
};
|
||||
@ -14,7 +14,8 @@ const createSingleTypeService = ({ model, strapi, utils }) => {
|
||||
* @return {Promise}
|
||||
*/
|
||||
find({ params } = {}) {
|
||||
return strapi.entityService.find(uid, { params: getFetchParams(params) });
|
||||
const normalizedParams = getFetchParams(params);
|
||||
return strapi.entityService.find(uid, { params: normalizedParams });
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
const { cloneDeep } = require('lodash/fp');
|
||||
const _ = require('lodash');
|
||||
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
|
||||
const { hasDraftAndPublish, getPrivateAttributes } = require('@strapi/utils').contentTypes;
|
||||
const {
|
||||
CREATED_AT_ATTRIBUTE,
|
||||
UPDATED_AT_ATTRIBUTE,
|
||||
@ -60,9 +60,7 @@ const createContentType = (uid, definition) => {
|
||||
|
||||
Object.defineProperty(schema, 'privateAttributes', {
|
||||
get() {
|
||||
// FIXME: to fix
|
||||
// return strapi.getModel(model.uid).privateAttributes;
|
||||
return [];
|
||||
return getPrivateAttributes(schema);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
rest: {
|
||||
defaultLimit: 25,
|
||||
maxLimit: 100,
|
||||
},
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user