| 
									
										
										
										
											2020-10-27 11:27:17 +01:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Converts the standard Strapi REST query params to a moe usable format for querying | 
					
						
							| 
									
										
										
										
											2021-03-09 01:13:15 -07:00
										 |  |  |  * You can read more here: https://strapi.io/documentation/developer-docs/latest/developer-resources/content-api/content-api.html#filters
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const _ = require('lodash'); | 
					
						
							| 
									
										
										
										
											2020-09-16 10:08:18 +02:00
										 |  |  | const { | 
					
						
							|  |  |  |   constants: { DP_PUB_STATES }, | 
					
						
							|  |  |  | } = require('./content-types'); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 13:22:40 +02:00
										 |  |  | const BOOLEAN_OPERATORS = ['or']; | 
					
						
							|  |  |  | const QUERY_OPERATORS = ['_where', '_or']; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  |  * Global converter | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |  * @param {Object} params | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  |  * @param defaults | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02:00
										 |  |  | const convertRestQueryParams = (params = {}, defaults = {}) => { | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   if (typeof params !== 'object' || params === null) { | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |       `convertRestQueryParams expected an object got ${params === null ? 'null' : typeof params}` | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02:00
										 |  |  |   let finalParams = Object.assign({ start: 0, limit: 100 }, defaults); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (Object.keys(params).length === 0) { | 
					
						
							|  |  |  |     return finalParams; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_.has(params, '_sort')) { | 
					
						
							| 
									
										
										
										
											2019-03-29 16:53:25 +01:00
										 |  |  |     Object.assign(finalParams, convertSortQueryParams(params._sort)); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_.has(params, '_start')) { | 
					
						
							| 
									
										
										
										
											2019-03-29 16:53:25 +01:00
										 |  |  |     Object.assign(finalParams, convertStartQueryParams(params._start)); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_.has(params, '_limit')) { | 
					
						
							| 
									
										
										
										
											2019-03-29 16:53:25 +01:00
										 |  |  |     Object.assign(finalParams, convertLimitQueryParams(params._limit)); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 10:08:18 +02:00
										 |  |  |   if (_.has(params, '_publicationState')) { | 
					
						
							|  |  |  |     Object.assign(finalParams, convertPublicationStateParams(params._publicationState)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 14:13:39 +02:00
										 |  |  |   const whereParams = convertExtraRootParams( | 
					
						
							|  |  |  |     _.omit(params, ['_sort', '_start', '_limit', '_where', '_publicationState']) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |   const whereClauses = []; | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |   if (_.keys(whereParams).length > 0) { | 
					
						
							|  |  |  |     whereClauses.push(...convertWhereParams(whereParams)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_.has(params, '_where')) { | 
					
						
							|  |  |  |     whereClauses.push(...convertWhereParams(params._where)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Object.assign(finalParams, { where: whereClauses }); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return finalParams; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 14:13:39 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Convert params prefixed with _ by removing the prefix after we have handle the internal params | 
					
						
							|  |  |  |  * NOTE: This is only a temporary patch for v3 to handle extra params coming from plugins | 
					
						
							|  |  |  |  * @param {object} params | 
					
						
							|  |  |  |  * @returns {object} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertExtraRootParams = params => { | 
					
						
							|  |  |  |   return Object.entries(params).reduce((acc, [key, value]) => { | 
					
						
							| 
									
										
										
										
											2021-04-08 14:47:05 +02:00
										 |  |  |     if (_.startsWith(key, '_') && !QUERY_OPERATORS.includes(key)) { | 
					
						
							| 
									
										
										
										
											2021-04-08 14:13:39 +02:00
										 |  |  |       acc[key.slice(1)] = value; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       acc[key] = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return acc; | 
					
						
							|  |  |  |   }, {}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Sort query parser | 
					
						
							|  |  |  |  * @param {string} sortQuery - ex: id:asc,price:desc | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertSortQueryParams = sortQuery => { | 
					
						
							|  |  |  |   if (typeof sortQuery !== 'string') { | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |     throw new Error(`convertSortQueryParams expected a string, got ${typeof sortQuery}`); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const sortKeys = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sortQuery.split(',').forEach(part => { | 
					
						
							|  |  |  |     // split field and order param with default order to ascending
 | 
					
						
							|  |  |  |     const [field, order = 'asc'] = part.split(':'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (field.length === 0) { | 
					
						
							|  |  |  |       throw new Error('Field cannot be empty'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!['asc', 'desc'].includes(order.toLocaleLowerCase())) { | 
					
						
							|  |  |  |       throw new Error('order can only be one of asc|desc|ASC|DESC'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sortKeys.push({ field, order: order.toLowerCase() }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     sort: sortKeys, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Start query parser | 
					
						
							|  |  |  |  * @param {string} startQuery - ex: id:asc,price:desc | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertStartQueryParams = startQuery => { | 
					
						
							|  |  |  |   const startAsANumber = _.toNumber(startQuery); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!_.isInteger(startAsANumber) || startAsANumber < 0) { | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |     throw new Error(`convertStartQueryParams expected a positive integer got ${startAsANumber}`); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     start: startAsANumber, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Limit query parser | 
					
						
							|  |  |  |  * @param {string} limitQuery - ex: id:asc,price:desc | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertLimitQueryParams = limitQuery => { | 
					
						
							|  |  |  |   const limitAsANumber = _.toNumber(limitQuery); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |   if (!_.isInteger(limitAsANumber) || (limitAsANumber !== -1 && limitAsANumber < 0)) { | 
					
						
							|  |  |  |     throw new Error(`convertLimitQueryParams expected a positive integer got ${limitAsANumber}`); | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     limit: limitAsANumber, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 10:08:18 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * publicationState query parser | 
					
						
							|  |  |  |  * @param {string} publicationState - eg: 'live', 'preview' | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertPublicationStateParams = publicationState => { | 
					
						
							|  |  |  |   if (!DP_PUB_STATES.includes(publicationState)) { | 
					
						
							|  |  |  |     throw new Error( | 
					
						
							|  |  |  |       `convertPublicationStateParams expected a value from: ${DP_PUB_STATES.join( | 
					
						
							|  |  |  |         ', ' | 
					
						
							|  |  |  |       )}. Got ${publicationState} instead`
 | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { publicationState }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | // List of all the possible filters
 | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  | const VALID_REST_OPERATORS = [ | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   'eq', | 
					
						
							|  |  |  |   'ne', | 
					
						
							|  |  |  |   'in', | 
					
						
							|  |  |  |   'nin', | 
					
						
							|  |  |  |   'contains', | 
					
						
							|  |  |  |   'ncontains', | 
					
						
							|  |  |  |   'containss', | 
					
						
							|  |  |  |   'ncontainss', | 
					
						
							|  |  |  |   'lt', | 
					
						
							|  |  |  |   'lte', | 
					
						
							|  |  |  |   'gt', | 
					
						
							|  |  |  |   'gte', | 
					
						
							| 
									
										
										
										
											2019-07-04 19:10:17 -03:00
										 |  |  |   'null', | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Parse where params | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertWhereParams = whereParams => { | 
					
						
							|  |  |  |   let finalWhere = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-23 09:44:43 +01:00
										 |  |  |   if (Array.isArray(whereParams)) { | 
					
						
							|  |  |  |     return whereParams.reduce((acc, whereParam) => { | 
					
						
							|  |  |  |       return acc.concat(convertWhereParams(whereParam)); | 
					
						
							|  |  |  |     }, []); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   Object.keys(whereParams).forEach(whereClause => { | 
					
						
							|  |  |  |     const { field, operator = 'eq', value } = convertWhereClause( | 
					
						
							|  |  |  |       whereClause, | 
					
						
							|  |  |  |       whereParams[whereClause] | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     finalWhere.push({ | 
					
						
							|  |  |  |       field, | 
					
						
							|  |  |  |       operator, | 
					
						
							|  |  |  |       value, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return finalWhere; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Parse single where param | 
					
						
							|  |  |  |  * @param {string} whereClause - Any possible where clause e.g: id_ne text_ncontains | 
					
						
							|  |  |  |  * @param {string} value - the value of the where clause e.g id_ne=value | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertWhereClause = (whereClause, value) => { | 
					
						
							|  |  |  |   const separatorIndex = whereClause.lastIndexOf('_'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // eq operator
 | 
					
						
							|  |  |  |   if (separatorIndex === -1) { | 
					
						
							|  |  |  |     return { field: whereClause, value }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // split field and operator
 | 
					
						
							|  |  |  |   const field = whereClause.substring(0, separatorIndex); | 
					
						
							|  |  |  |   const operator = whereClause.slice(separatorIndex + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 20:20:02 +02:00
										 |  |  |   if (BOOLEAN_OPERATORS.includes(operator) && field === '') { | 
					
						
							|  |  |  |     return { field: null, operator, value: [].concat(value).map(convertWhereParams) }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |   // the field as underscores
 | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  |   if (!VALID_REST_OPERATORS.includes(operator)) { | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |     return { field: whereClause, value }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { field, operator, value }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  | module.exports = { | 
					
						
							|  |  |  |   convertRestQueryParams, | 
					
						
							|  |  |  |   VALID_REST_OPERATORS, | 
					
						
							| 
									
										
										
										
											2020-10-15 13:22:40 +02:00
										 |  |  |   QUERY_OPERATORS, | 
					
						
							| 
									
										
										
										
											2020-06-29 16:32:14 +02:00
										 |  |  | }; |