| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Converts the standard Strapi REST query params to a moe usable format for querying | 
					
						
							| 
									
										
										
										
											2019-06-01 08:51:42 -07:00
										 |  |  |  * You can read more here: https://strapi.io/documentation/3.0.0-beta.x/guides/filters.html
 | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const _ = require('lodash'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Global convertor | 
					
						
							|  |  |  |  * @param {Object} params | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											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( | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02: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
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const whereParams = _.omit(params, ['_sort', '_start', '_limit']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (_.keys(whereParams).length > 0) | 
					
						
							| 
									
										
										
										
											2019-03-29 16:53:25 +01:00
										 |  |  |     Object.assign(finalParams, { | 
					
						
							| 
									
										
										
										
											2019-03-13 19:27:18 +01:00
										 |  |  |       where: convertWhereParams(whereParams), | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return finalParams; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Sort query parser | 
					
						
							|  |  |  |  * @param {string} sortQuery - ex: id:asc,price:desc | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const convertSortQueryParams = sortQuery => { | 
					
						
							|  |  |  |   if (typeof sortQuery !== 'string') { | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02: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) { | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02: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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-16 17:23:58 +02: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, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // List of all the possible filters
 | 
					
						
							|  |  |  | const VALID_OPERATORS = [ | 
					
						
							|  |  |  |   '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 = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // the field as underscores
 | 
					
						
							|  |  |  |   if (!VALID_OPERATORS.includes(operator)) { | 
					
						
							|  |  |  |     return { field: whereClause, value }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { field, operator, value }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = convertRestQueryParams; |