'use strict'; const { merge, pipe, omit, isNil } = require('lodash/fp'); const { PaginationError } = require('./errors'); const STRAPI_DEFAULTS = { offset: { start: 0, limit: 10, }, page: { page: 1, pageSize: 10, }, }; const paginationAttributes = ['start', 'limit', 'page', 'pageSize']; const withMaxLimit = (limit, maxLimit = -1) => { if (maxLimit === -1 || limit < maxLimit) { return limit; } return maxLimit; }; // Ensure minimum page & pageSize values (page >= 1, pageSize >= 0, start >= 0, limit >= 0) const ensureMinValues = ({ start, limit }) => ({ start: Math.max(start, 0), limit: limit === -1 ? limit : Math.max(limit, 1), }); const ensureMaxValues = (maxLimit = -1) => ({ start, limit }) => ({ start, limit: withMaxLimit(limit, maxLimit), }); // Apply maxLimit as the limit when limit is -1 const withNoLimit = (pagination, maxLimit = -1) => ({ ...pagination, limit: pagination.limit === -1 ? maxLimit : pagination.limit, }); const withDefaultPagination = (args, { defaults = {}, maxLimit = -1 } = {}) => { const defaultValues = merge(STRAPI_DEFAULTS, defaults); const usePagePagination = !isNil(args.page) || !isNil(args.pageSize); const useOffsetPagination = !isNil(args.start) || !isNil(args.limit); const ensureValidValues = pipe(ensureMinValues, ensureMaxValues(maxLimit)); // If there is no pagination attribute, don't modify the payload if (!usePagePagination && !useOffsetPagination) { return merge(args, ensureValidValues(defaultValues.offset)); } // If there is page & offset pagination attributes, throw an error if (usePagePagination && useOffsetPagination) { throw new PaginationError('Cannot use both page & offset pagination in the same query'); } const pagination = {}; // Start / Limit if (useOffsetPagination) { const { start, limit } = merge(defaultValues.offset, args); Object.assign(pagination, { start, limit }); } // Page / PageSize if (usePagePagination) { const { page, pageSize } = merge(defaultValues.page, { ...args, pageSize: Math.max(1, args.pageSize), }); Object.assign(pagination, { start: (page - 1) * pageSize, limit: pageSize, }); } // Handle -1 limit Object.assign(pagination, withNoLimit(pagination, maxLimit)); const replacePaginationAttributes = pipe( // Remove pagination attributes omit(paginationAttributes), // Merge the object with the new pagination + ensure minimum & maximum values merge(ensureValidValues(pagination)) ); return replacePaginationAttributes(args); }; module.exports = { withDefaultPagination };