mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 18:08:11 +00:00 
			
		
		
		
	Implement pagination logic in core api
This commit is contained in:
		
							parent
							
								
									b44a552eee
								
							
						
					
					
						commit
						b781213b01
					
				| @ -1,7 +1,7 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| const _ = require('lodash'); | const _ = require('lodash'); | ||||||
| const { createService, getFetchParams } = require('../service'); | const { createService } = require('../service'); | ||||||
| 
 | 
 | ||||||
| const maxLimit = 50; | const maxLimit = 50; | ||||||
| const defaultLimit = 20; | const defaultLimit = 20; | ||||||
| @ -82,7 +82,7 @@ describe('Default Service', () => { | |||||||
|         await service.createOrUpdate(input); |         await service.createOrUpdate(input); | ||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { |         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { | ||||||
|           params: { publicationState: 'live', pagination: { limit: defaultLimit } }, |           params: { publicationState: 'live' }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.create).toHaveBeenCalledWith('testModel', { data: input }); |         expect(strapi.entityService.create).toHaveBeenCalledWith('testModel', { data: input }); | ||||||
| @ -111,7 +111,7 @@ describe('Default Service', () => { | |||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { |         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { | ||||||
|           populate: undefined, |           populate: undefined, | ||||||
|           params: { publicationState: 'live', pagination: { limit: defaultLimit } }, |           params: { publicationState: 'live' }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.update).toHaveBeenCalledWith('testModel', 1, { |         expect(strapi.entityService.update).toHaveBeenCalledWith('testModel', 1, { | ||||||
| @ -138,7 +138,7 @@ describe('Default Service', () => { | |||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { |         expect(strapi.entityService.find).toHaveBeenCalledWith('testModel', { | ||||||
|           populate: undefined, |           populate: undefined, | ||||||
|           params: { publicationState: 'live', pagination: { limit: defaultLimit } }, |           params: { publicationState: 'live' }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         expect(strapi.entityService.delete).toHaveBeenCalledWith('testModel', 1); |         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, |  | ||||||
|       }, |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  | |||||||
| @ -8,10 +8,10 @@ const { | |||||||
| } = require('@strapi/utils').contentTypes; | } = require('@strapi/utils').contentTypes; | ||||||
| 
 | 
 | ||||||
| const { | const { | ||||||
|   applyDefaultPagination, |   getPaginationInfo, | ||||||
|   convertPagedToStartLimit, |   convertPagedToStartLimit, | ||||||
|   shouldCount, |   shouldCount, | ||||||
|   formatPaginationResponse, |   transformPaginationResponse, | ||||||
| } = require('./pagination'); | } = require('./pagination'); | ||||||
| 
 | 
 | ||||||
| const setPublishedAt = data => { | const setPublishedAt = data => { | ||||||
| @ -31,7 +31,7 @@ const createCollectionTypeService = ({ model, strapi, utils }) => { | |||||||
|     async find(opts = {}) { |     async find(opts = {}) { | ||||||
|       const params = getFetchParams(opts.params); |       const params = getFetchParams(opts.params); | ||||||
| 
 | 
 | ||||||
|       const paginationInfo = applyDefaultPagination(params); |       const paginationInfo = getPaginationInfo(params); | ||||||
| 
 | 
 | ||||||
|       const results = await strapi.entityService.find(uid, { |       const results = await strapi.entityService.find(uid, { | ||||||
|         params: { ...params, ...convertPagedToStartLimit(paginationInfo) }, |         params: { ...params, ...convertPagedToStartLimit(paginationInfo) }, | ||||||
| @ -44,7 +44,7 @@ const createCollectionTypeService = ({ model, strapi, utils }) => { | |||||||
| 
 | 
 | ||||||
|         return { |         return { | ||||||
|           results, |           results, | ||||||
|           pagination: formatPaginationResponse(paginationInfo, count), |           pagination: transformPaginationResponse(paginationInfo, count), | ||||||
|         }; |         }; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,14 +1,15 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| const _ = require('lodash'); | const _ = require('lodash'); | ||||||
|  | const { has, toNumber, isUndefined, isPlainObject } = require('lodash/fp'); | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Default limit values from config |  * Default limit values from config | ||||||
|  * @return {{maxLimit: number, defaultLimit: number}} |  * @return {{maxLimit: number, defaultLimit: number}} | ||||||
|  */ |  */ | ||||||
| const getLimitConfigDefaults = () => ({ | const getLimitConfigDefaults = () => ({ | ||||||
|   defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 25)), |   defaultLimit: toNumber(strapi.config.get('api.rest.defaultLimit', 25)), | ||||||
|   maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null, |   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)); |   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(); |   const { defaultLimit, maxLimit } = getLimitConfigDefaults(); | ||||||
| 
 | 
 | ||||||
|   if (_.isUndefined(params.pagination) || !_.isPlainObject(params.pagination)) { |   if (isUndefined(params.pagination) || !isPlainObject(params.pagination)) { | ||||||
|     return { |     return { | ||||||
|       start: 0, |       start: 0, | ||||||
|       limit: defaultLimit, |       limit: defaultLimit, | ||||||
| @ -45,23 +49,27 @@ const applyDefaultPagination = params => { | |||||||
| 
 | 
 | ||||||
|   const { pagination } = params; |   const { pagination } = params; | ||||||
| 
 | 
 | ||||||
|   if (!_.isUndefined(pagination.pageSize) || !_.isUndefined(pagination.page)) { |   if (isOffsetPagination(pagination) && isPagedPagination(pagination)) { | ||||||
|     const pageSize = _.isUndefined(pagination.pageSize) |     throw new Error('Invalid pagination parameters. Expected either start/limit or page/pageSize'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (isPagedPagination(pagination)) { | ||||||
|  |     const pageSize = isUndefined(pagination.pageSize) | ||||||
|       ? defaultLimit |       ? defaultLimit | ||||||
|       : Math.max(1, _.toNumber(pagination.pageSize)); |       : Math.max(1, toNumber(pagination.pageSize)); | ||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|       page: Math.max(1, _.toNumber(pagination.page || 1)), |       page: Math.max(1, toNumber(pagination.page || 1)), | ||||||
|       pageSize: applyMaxLimit(pageSize, maxLimit), |       pageSize: applyMaxLimit(pageSize, maxLimit), | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const limit = _.isUndefined(pagination.limit) |   const limit = isUndefined(pagination.limit) | ||||||
|     ? defaultLimit |     ? defaultLimit | ||||||
|     : Math.max(1, _.toNumber(pagination.limit)); |     : Math.max(1, toNumber(pagination.limit)); | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     start: Math.max(0, _.toNumber(pagination.start || 0)), |     start: Math.max(0, toNumber(pagination.start || 0)), | ||||||
|     limit: applyMaxLimit(limit, maxLimit), |     limit: applyMaxLimit(limit, maxLimit), | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| @ -78,7 +86,7 @@ const convertPagedToStartLimit = pagination => { | |||||||
|   return pagination; |   return pagination; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const formatPaginationResponse = (paginationInfo, count) => { | const transformPaginationResponse = (paginationInfo, count) => { | ||||||
|   if (paginationInfo.page) { |   if (paginationInfo.page) { | ||||||
|     return { |     return { | ||||||
|       ...paginationInfo, |       ...paginationInfo, | ||||||
| @ -94,8 +102,8 @@ const formatPaginationResponse = (paginationInfo, count) => { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| module.exports = { | module.exports = { | ||||||
|   applyDefaultPagination, |   getPaginationInfo, | ||||||
|   convertPagedToStartLimit, |   convertPagedToStartLimit, | ||||||
|  |   transformPaginationResponse, | ||||||
|   shouldCount, |   shouldCount, | ||||||
|   formatPaginationResponse, |  | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -61,6 +61,7 @@ module.exports = strapi => { | |||||||
|               ], |               ], | ||||||
|             }); |             }); | ||||||
|           } |           } | ||||||
|  | 
 | ||||||
|           throw e; |           throw e; | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Alexandre Bodin
						Alexandre Bodin