| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  | const _ = require('lodash'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  | module.exports = { | 
					
						
							| 
									
										
										
										
											2017-08-29 19:34:34 +02:00
										 |  |  |  |   find: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-12-07 15:44:20 +01:00
										 |  |  |  |     return this.query(function(qb) { | 
					
						
							|  |  |  |  |       _.forEach(params.where, (where, key) => { | 
					
						
							|  |  |  |  |         qb.where(key, where[0].symbol, where[0].value); | 
					
						
							| 
									
										
										
										
											2017-06-18 17:23:58 +02:00
										 |  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2017-12-07 15:44:20 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (params.sort) { | 
					
						
							|  |  |  |  |         qb.orderBy(params.sort); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       qb.offset(params.skip); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       qb.limit(params.limit); | 
					
						
							|  |  |  |  |     }).fetchAll({ | 
					
						
							|  |  |  |  |       withRelated: this.associations.map(x => x.alias) | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-29 19:34:34 +02:00
										 |  |  |  |   count: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |     return await this | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |       .forge() | 
					
						
							|  |  |  |  |       .count(); | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |   findOne: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |     const record = await this | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |       .forge({ | 
					
						
							|  |  |  |  |         [this.primaryKey]: params[this.primaryKey] | 
					
						
							|  |  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |       .fetch({ | 
					
						
							| 
									
										
										
										
											2017-10-26 17:21:23 +02:00
										 |  |  |  |         withRelated: this.associations.map(x => x.alias) | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |       }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return record ? record.toJSON() : record; | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |   create: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |     const entry = await this | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |       .forge() | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |       .save(Object.keys(params.values).reduce((acc, current) => { | 
					
						
							|  |  |  |  |       if (this._attributes[current].type) { | 
					
						
							|  |  |  |  |         acc[current] = params.values[current]; | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return acc; | 
					
						
							| 
									
										
										
										
											2017-12-06 15:58:20 +01:00
										 |  |  |  |     }, {})) | 
					
						
							|  |  |  |  |     .catch((err) => { | 
					
						
							| 
									
										
										
										
											2017-12-07 14:56:25 +01:00
										 |  |  |  |       if (err.detail) { | 
					
						
							|  |  |  |  |         const field = _.last(_.words(err.detail.split('=')[0])); | 
					
						
							|  |  |  |  |         err = { message: `This ${field} is already taken`, field }; | 
					
						
							|  |  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-12-06 15:58:20 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-07 14:56:25 +01:00
										 |  |  |  |       throw err; | 
					
						
							| 
									
										
										
										
											2017-12-06 15:58:20 +01:00
										 |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     return module.exports.update.call(this, { | 
					
						
							|  |  |  |  |       [this.primaryKey]: entry[this.primaryKey], | 
					
						
							|  |  |  |  |       values: _.merge({ | 
					
						
							|  |  |  |  |         id: entry[this.primaryKey] | 
					
						
							|  |  |  |  |       }, params.values) | 
					
						
							|  |  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |   update: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  |     const virtualFields = []; | 
					
						
							|  |  |  |  |     const response = await module.exports.findOne.call(this, params); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // Only update fields which are on this document.
 | 
					
						
							|  |  |  |  |     const values = params.parseRelationships === false ? params.values : Object.keys(JSON.parse(JSON.stringify(params.values))).reduce((acc, current) => { | 
					
						
							|  |  |  |  |       const association = this.associations.filter(x => x.alias === current)[0]; | 
					
						
							|  |  |  |  |       const details = this._attributes[current]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (_.get(this._attributes, `${current}.isVirtual`) !== true && _.isUndefined(association)) { | 
					
						
							|  |  |  |  |         acc[current] = params.values[current]; | 
					
						
							|  |  |  |  |       } else { | 
					
						
							|  |  |  |  |         switch (association.nature) { | 
					
						
							|  |  |  |  |           case 'oneToOne': | 
					
						
							|  |  |  |  |             if (response[current] !== params.values[current]) { | 
					
						
							|  |  |  |  |               const value = _.isNull(params.values[current]) ? response[current] : params.values; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               const recordId = _.isNull(params.values[current]) ? value[this.primaryKey] || value.id || value._id : value[current]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               if (response[current] && _.isObject(response[current]) && response[current][this.primaryKey] !== value[current]) { | 
					
						
							|  |  |  |  |                 virtualFields.push( | 
					
						
							|  |  |  |  |                   strapi.query(details.collection || details.model).update({ | 
					
						
							|  |  |  |  |                     id: response[current][this.primaryKey], | 
					
						
							|  |  |  |  |                     values: { | 
					
						
							|  |  |  |  |                       [details.via]: null | 
					
						
							|  |  |  |  |                     }, | 
					
						
							|  |  |  |  |                     parseRelationships: false | 
					
						
							|  |  |  |  |                   }) | 
					
						
							|  |  |  |  |                 ); | 
					
						
							|  |  |  |  |               } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               // Remove previous relationship asynchronously if it exists.
 | 
					
						
							|  |  |  |  |               virtualFields.push( | 
					
						
							|  |  |  |  |                 strapi.query(details.model || details.collection).findOne({ id : recordId }) | 
					
						
							|  |  |  |  |                   .then(record => { | 
					
						
							|  |  |  |  |                     if (record && _.isObject(record[details.via])) { | 
					
						
							|  |  |  |  |                       return module.exports.update.call(this, { | 
					
						
							|  |  |  |  |                         id: record[details.via][this.primaryKey] || record[details.via].id, | 
					
						
							|  |  |  |  |                         values: { | 
					
						
							|  |  |  |  |                           [current]: null | 
					
						
							|  |  |  |  |                         }, | 
					
						
							|  |  |  |  |                         parseRelationships: false | 
					
						
							|  |  |  |  |                       }); | 
					
						
							|  |  |  |  |                     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |                     return Promise.resolve(); | 
					
						
							|  |  |  |  |                   }) | 
					
						
							|  |  |  |  |               ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               // Update the record on the other side.
 | 
					
						
							|  |  |  |  |               // When params.values[current] is null this means that we are removing the relation.
 | 
					
						
							|  |  |  |  |               virtualFields.push(strapi.query(details.model || details.collection).update({ | 
					
						
							|  |  |  |  |                 id: recordId, | 
					
						
							|  |  |  |  |                 values: { | 
					
						
							|  |  |  |  |                   [details.via]: _.isNull(params.values[current]) ? null : value[this.primaryKey] || value.id || value._id | 
					
						
							|  |  |  |  |                 }, | 
					
						
							|  |  |  |  |                 parseRelationships: false | 
					
						
							|  |  |  |  |               })); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               acc[current] = _.isNull(params.values[current]) ? null : value[current]; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             break; | 
					
						
							|  |  |  |  |           case 'oneToMany': | 
					
						
							|  |  |  |  |           case 'manyToOne': | 
					
						
							|  |  |  |  |           case 'manyToMany': | 
					
						
							|  |  |  |  |             if (details.dominant === true) { | 
					
						
							|  |  |  |  |               acc[current] = params.values[current]; | 
					
						
							|  |  |  |  |             } else if (response[current] && _.isArray(response[current]) && current !== 'id') { | 
					
						
							|  |  |  |  |               // Records to add in the relation.
 | 
					
						
							|  |  |  |  |               const toAdd = _.differenceWith(params.values[current], response[current], (a, b) => | 
					
						
							|  |  |  |  |                 a[this.primaryKey].toString() === b[this.primaryKey].toString() | 
					
						
							|  |  |  |  |               ); | 
					
						
							|  |  |  |  |               // Records to remove in the relation.
 | 
					
						
							|  |  |  |  |               const toRemove = _.differenceWith(response[current], params.values[current], (a, b) => | 
					
						
							|  |  |  |  |                 a[this.primaryKey].toString() === b[this.primaryKey].toString() | 
					
						
							|  |  |  |  |               ) | 
					
						
							|  |  |  |  |                 .filter(x => toAdd.find(y => x.id === y.id) === undefined); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               // Push the work into the flow process.
 | 
					
						
							|  |  |  |  |               toAdd.forEach(value => { | 
					
						
							| 
									
										
										
										
											2017-10-23 17:35:00 +02:00
										 |  |  |  |                 value[details.via] = params.values[this.primaryKey] || params[this.primaryKey]; | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |                 virtualFields.push(strapi.query(details.model || details.collection).addRelation({ | 
					
						
							|  |  |  |  |                   id: value[this.primaryKey] || value.id || value._id, | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |                   values: association.nature === 'manyToMany' ? params.values : value, | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  |                   foreignKey: current | 
					
						
							|  |  |  |  |                 })); | 
					
						
							|  |  |  |  |               }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |               toRemove.forEach(value => { | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |                 value[details.via] = null; | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |                 virtualFields.push(strapi.query(details.model || details.collection).removeRelation({ | 
					
						
							|  |  |  |  |                   id: value[this.primaryKey] || value.id || value._id, | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |                   values: association.nature === 'manyToMany' ? params.values : value, | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  |                   foreignKey: current | 
					
						
							|  |  |  |  |                 })); | 
					
						
							|  |  |  |  |               }); | 
					
						
							|  |  |  |  |             } else if (_.get(this._attributes, `${current}.isVirtual`) !== true) { | 
					
						
							|  |  |  |  |               acc[current] = params.values[current]; | 
					
						
							|  |  |  |  |             } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |             break; | 
					
						
							|  |  |  |  |           default: | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       return acc; | 
					
						
							|  |  |  |  |     }, {}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 15:25:10 +02:00
										 |  |  |  |     if (!_.isEmpty(values)) { | 
					
						
							|  |  |  |  |       virtualFields.push(this | 
					
						
							|  |  |  |  |         .forge({ | 
					
						
							|  |  |  |  |           [this.primaryKey]: params[this.primaryKey] | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         .save(values, { | 
					
						
							|  |  |  |  |           patch: true | 
					
						
							|  |  |  |  |         })); | 
					
						
							|  |  |  |  |     } else { | 
					
						
							|  |  |  |  |       virtualFields.push(Promise.resolve(_.assign(response, params.values))); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-18 18:20:33 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     // Update virtuals fields.
 | 
					
						
							|  |  |  |  |     const process = await Promise.all(virtualFields); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return process[process.length - 1]; | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |   delete: async function (params) { | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |     return await this | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |       .forge({ | 
					
						
							| 
									
										
										
										
											2017-09-20 18:15:06 +02:00
										 |  |  |  |         [this.primaryKey]: params.id | 
					
						
							| 
									
										
										
										
											2017-09-14 16:33:56 +02:00
										 |  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |       .destroy(); | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   addRelation: async function (params) { | 
					
						
							|  |  |  |  |     const association = this.associations.filter(x => x.via === params.foreignKey)[0]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (!association) { | 
					
						
							|  |  |  |  |       // Resolve silently.
 | 
					
						
							|  |  |  |  |       return Promise.resolve(); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     switch (association.nature) { | 
					
						
							|  |  |  |  |       case 'oneToOne': | 
					
						
							|  |  |  |  |       case 'oneToMany': | 
					
						
							|  |  |  |  |         return module.exports.update.call(this, params); | 
					
						
							|  |  |  |  |       case 'manyToMany': | 
					
						
							|  |  |  |  |         return this.forge({ | 
					
						
							|  |  |  |  |           [this.primaryKey]: params[this.primaryKey] | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |         })[association.alias]().attach(params.values[this.primaryKey]); | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |       default: | 
					
						
							|  |  |  |  |         // Resolve silently.
 | 
					
						
							|  |  |  |  |         return Promise.resolve(); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   removeRelation: async function (params) { | 
					
						
							|  |  |  |  |     const association = this.associations.filter(x => x.via === params.foreignKey)[0]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (!association) { | 
					
						
							|  |  |  |  |       // Resolve silently.
 | 
					
						
							|  |  |  |  |       return Promise.resolve(); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     switch (association.nature) { | 
					
						
							|  |  |  |  |       case 'oneToOne': | 
					
						
							|  |  |  |  |       case 'oneToMany': | 
					
						
							|  |  |  |  |         return module.exports.update.call(this, params); | 
					
						
							|  |  |  |  |       case 'manyToMany': | 
					
						
							|  |  |  |  |         return this.forge({ | 
					
						
							|  |  |  |  |           [this.primaryKey]: params[this.primaryKey] | 
					
						
							| 
									
										
										
										
											2017-09-19 11:17:04 +02:00
										 |  |  |  |         })[association.alias]().detach(params.values[this.primaryKey]); | 
					
						
							| 
									
										
										
										
											2017-09-14 18:47:10 +02:00
										 |  |  |  |       default: | 
					
						
							|  |  |  |  |         // Resolve silently.
 | 
					
						
							|  |  |  |  |         return Promise.resolve(); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-06-17 17:01:50 +02:00
										 |  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-08-29 19:34:34 +02:00
										 |  |  |  | }; |