| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  | const _ = require('lodash/fp'); | 
					
						
							|  |  |  | const types = require('./types'); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | const { createField } = require('./fields'); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | const { createQueryBuilder } = require('./query'); | 
					
						
							|  |  |  | const { createRepository } = require('./entity-repository'); | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  | const { isBidirectional, isOneToAny } = require('./metadata/relations'); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const toId = (value) => value.id || value; | 
					
						
							|  |  |  | const toIds = (value) => _.castArray(value || []).map(toId); | 
					
						
							| 
									
										
										
										
											2021-07-30 21:15:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const isValidId = (value) => _.isString(value) || _.isInteger(value); | 
					
						
							|  |  |  | const toAssocs = (data) => { | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |   return _.castArray(data) | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |     .filter((datum) => !_.isNil(datum)) | 
					
						
							|  |  |  |     .map((datum) => { | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |       // if it is a string or an integer return an obj with id = to datum
 | 
					
						
							|  |  |  |       if (isValidId(datum)) { | 
					
						
							|  |  |  |         return { id: datum, __pivot: {} }; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // if it is an object check it has at least a valid id
 | 
					
						
							|  |  |  |       if (!_.has('id', datum) || !isValidId(datum.id)) { | 
					
						
							|  |  |  |         throw new Error(`Invalid id, expected a string or integer, got ${datum}`); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return datum; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 10:49:43 +02:00
										 |  |  | const processData = (metadata, data = {}, { withDefaults = false } = {}) => { | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  |   const { attributes } = metadata; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |   const obj = {}; | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |   for (const attributeName in attributes) { | 
					
						
							|  |  |  |     const attribute = attributes[attributeName]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |     if (types.isScalar(attribute.type)) { | 
					
						
							|  |  |  |       const field = createField(attribute); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |       if (_.isUndefined(data[attributeName])) { | 
					
						
							|  |  |  |         if (!_.isUndefined(attribute.default) && withDefaults) { | 
					
						
							|  |  |  |           if (typeof attribute.default === 'function') { | 
					
						
							|  |  |  |             obj[attributeName] = attribute.default(); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             obj[attributeName] = attribute.default; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |       if (typeof field.validate === 'function' && data[attributeName] !== null) { | 
					
						
							|  |  |  |         field.validate(data[attributeName]); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-06-30 20:00:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 21:37:44 +02:00
										 |  |  |       const val = data[attributeName] === null ? null : field.toDB(data[attributeName]); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 21:37:44 +02:00
										 |  |  |       obj[attributeName] = val; | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (types.isRelation(attribute.type)) { | 
					
						
							|  |  |  |       // oneToOne & manyToOne
 | 
					
						
							|  |  |  |       if (attribute.joinColumn && attribute.owner) { | 
					
						
							|  |  |  |         const joinColumnName = attribute.joinColumn.name; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |         // allow setting to null
 | 
					
						
							|  |  |  |         const attrValue = !_.isUndefined(data[attributeName]) | 
					
						
							|  |  |  |           ? data[attributeName] | 
					
						
							|  |  |  |           : data[joinColumnName]; | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!_.isUndefined(attrValue)) { | 
					
						
							|  |  |  |           obj[joinColumnName] = attrValue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (attribute.morphColumn && attribute.owner) { | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |         const { idColumn, typeColumn, typeField = '__type' } = attribute.morphColumn; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const value = data[attributeName]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |         if (value === null) { | 
					
						
							|  |  |  |           Object.assign(obj, { | 
					
						
							|  |  |  |             [idColumn.name]: null, | 
					
						
							|  |  |  |             [typeColumn.name]: null, | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |         if (!_.isUndefined(value)) { | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |           if (!_.has('id', value) || !_.has(typeField, value)) { | 
					
						
							|  |  |  |             throw new Error(`Expects properties ${typeField} an id to make a morph association`); | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |           Object.assign(obj, { | 
					
						
							|  |  |  |             [idColumn.name]: value.id, | 
					
						
							|  |  |  |             [typeColumn.name]: value[typeField], | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return obj; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const createEntityManager = (db) => { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |   const repoMap = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |     async findOne(uid, params) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeFindOne', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const result = await this.createQueryBuilder(uid).init(params).first().execute(); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterFindOne', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // should we name it findOne because people are used to it ?
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |     async findMany(uid, params) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeFindMany', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const result = await this.createQueryBuilder(uid).init(params).execute(); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterFindMany', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |     async count(uid, params) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeCount', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const res = await this.createQueryBuilder(uid) | 
					
						
							| 
									
										
										
										
											2021-10-13 14:06:16 +02:00
										 |  |  |         .init(_.pick(['_q', 'where', 'filters'], params)) | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |         .count() | 
					
						
							|  |  |  |         .first() | 
					
						
							|  |  |  |         .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const result = Number(res.count); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterCount', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     async create(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeCreate', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const metadata = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |       const { data } = params; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (!_.isPlainObject(data)) { | 
					
						
							|  |  |  |         throw new Error('Create expects a data object'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 10:49:43 +02:00
										 |  |  |       const dataToInsert = processData(metadata, data, { withDefaults: true }); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const res = await this.createQueryBuilder(uid).insert(dataToInsert).execute(); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 19:41:16 +01:00
										 |  |  |       const id = res[0].id || res[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |       await this.attachRelations(uid, id, data); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 14:06:16 +02:00
										 |  |  |       // TODO: in case there is no select or populate specified return the inserted data ?
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       // TODO: do not trigger the findOne lifecycles ?
 | 
					
						
							| 
									
										
										
										
											2021-08-04 17:47:38 +02:00
										 |  |  |       const result = await this.findOne(uid, { | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |         where: { id }, | 
					
						
							|  |  |  |         select: params.select, | 
					
						
							|  |  |  |         populate: params.populate, | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterCreate', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |     // TODO: where do we handle relation processing for many queries ?
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     async createMany(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeCreateMany', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       const metadata = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |       const { data } = params; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (!_.isArray(data)) { | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |         throw new Error('CreateMany expects data to be an array'); | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const dataToInsert = data.map((datum) => | 
					
						
							|  |  |  |         processData(metadata, datum, { withDefaults: true }) | 
					
						
							|  |  |  |       ); | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  |       if (_.isEmpty(dataToInsert)) { | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |         throw new Error('Nothing to insert'); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       await this.createQueryBuilder(uid).insert(dataToInsert).execute(); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const result = { count: data.length }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterCreateMany', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     async update(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeUpdate', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |       const metadata = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const { where, data } = params; | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-30 20:00:03 +02:00
										 |  |  |       if (!_.isPlainObject(data)) { | 
					
						
							|  |  |  |         throw new Error('Update requires a data object'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (_.isEmpty(where)) { | 
					
						
							|  |  |  |         throw new Error('Update requires a where parameter'); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const entity = await this.createQueryBuilder(uid).select('id').where(where).first().execute(); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (!entity) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const { id } = entity; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 10:49:43 +02:00
										 |  |  |       const dataToUpdate = processData(metadata, data); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (!_.isEmpty(dataToUpdate)) { | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |         await this.createQueryBuilder(uid).where({ id }).update(dataToUpdate).execute(); | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |       await this.updateRelations(uid, id, data); | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       // TODO: do not trigger the findOne lifecycles ?
 | 
					
						
							| 
									
										
										
										
											2021-08-04 17:47:38 +02:00
										 |  |  |       const result = await this.findOne(uid, { | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |         where: { id }, | 
					
						
							|  |  |  |         select: params.select, | 
					
						
							|  |  |  |         populate: params.populate, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterUpdate', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |     // TODO: where do we handle relation processing for many queries ?
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     async updateMany(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeUpdateMany', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 15:37:20 +02:00
										 |  |  |       const metadata = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const { where, data } = params; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 10:49:43 +02:00
										 |  |  |       const dataToUpdate = processData(metadata, data); | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  |       if (_.isEmpty(dataToUpdate)) { | 
					
						
							|  |  |  |         throw new Error('Update requires data'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       const updatedRows = await this.createQueryBuilder(uid) | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |         .where(where) | 
					
						
							| 
									
										
										
										
											2021-06-22 17:13:11 +02:00
										 |  |  |         .update(dataToUpdate) | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |         .execute(); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const result = { count: updatedRows }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterUpdateMany', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     async delete(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeDelete', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       const { where, select, populate } = params; | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       if (_.isEmpty(where)) { | 
					
						
							|  |  |  |         throw new Error('Delete requires a where parameter'); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-13 14:06:16 +02:00
										 |  |  |       // TODO: do not trigger the findOne lifecycles ?
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       const entity = await this.findOne(uid, { | 
					
						
							|  |  |  |         select: select && ['id'].concat(select), | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |         where, | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |         populate, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!entity) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const { id } = entity; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       await this.createQueryBuilder(uid).where({ id }).delete().execute(); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |       await this.deleteRelations(uid, id); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 13:20:14 +01:00
										 |  |  |       await db.lifecycles.run('afterDelete', uid, { params, result: entity }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |       return entity; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 12:07:32 +02:00
										 |  |  |     // TODO: where do we handle relation processing for many queries ?
 | 
					
						
							|  |  |  |     async deleteMany(uid, params = {}) { | 
					
						
							| 
									
										
										
										
											2022-04-04 19:22:05 +02:00
										 |  |  |       const states = await db.lifecycles.run('beforeDeleteMany', uid, { params }); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |       const { where } = params; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       const deletedRows = await this.createQueryBuilder(uid).where(where).delete().execute(); | 
					
						
							| 
									
										
										
										
											2021-06-24 18:28:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |       const result = { count: deletedRows }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-23 10:26:10 +02:00
										 |  |  |       await db.lifecycles.run('afterDeleteMany', uid, { params, result }, states); | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return result; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Attach relations to a new entity | 
					
						
							| 
									
										
										
										
											2021-06-30 21:17:32 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |      * @param {EntityManager} em - entity manager instance | 
					
						
							|  |  |  |      * @param {Metadata} metadata - model metadta | 
					
						
							|  |  |  |      * @param {ID} id - entity ID | 
					
						
							|  |  |  |      * @param {object} data - data received for creation | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-07-05 18:35:16 +02:00
										 |  |  |     // TODO: wrap Transaction
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |     async attachRelations(uid, id, data) { | 
					
						
							|  |  |  |       const { attributes } = db.metadata.get(uid); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |       for (const attributeName in attributes) { | 
					
						
							|  |  |  |         const attribute = attributes[attributeName]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |         const isValidLink = _.has(attributeName, data) && !_.isNil(data[attributeName]); | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.type !== 'relation' || !isValidLink) { | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |         if (attribute.relation === 'morphOne' || attribute.relation === 'morphMany') { | 
					
						
							|  |  |  |           const { target, morphBy } = attribute; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           const targetAttribute = db.metadata.get(target).attributes[morphBy]; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           if (targetAttribute.relation === 'morphToOne') { | 
					
						
							|  |  |  |             // set columns
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = targetAttribute.morphColumn; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             await this.createQueryBuilder(target) | 
					
						
							|  |  |  |               .update({ [idColumn.name]: id, [typeColumn.name]: uid }) | 
					
						
							| 
									
										
										
										
											2021-07-30 21:15:58 +02:00
										 |  |  |               .where({ id: toId(data[attributeName]) }) | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |               .execute(); | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |           } else if (targetAttribute.relation === 'morphToMany') { | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             const { joinTable } = targetAttribute; | 
					
						
							|  |  |  |             const { joinColumn, morphColumn } = joinTable; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |             const rows = toAssocs(data[attributeName]).map((data, idx) => { | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               return { | 
					
						
							|  |  |  |                 [joinColumn.name]: data.id, | 
					
						
							|  |  |  |                 [idColumn.name]: id, | 
					
						
							|  |  |  |                 [typeColumn.name]: uid, | 
					
						
							|  |  |  |                 ...(joinTable.on || {}), | 
					
						
							|  |  |  |                 ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |                 order: idx + 1, | 
					
						
							|  |  |  |                 field: attributeName, | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               }; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (_.isEmpty(rows)) { | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |             await this.createQueryBuilder(joinTable.name).insert(rows).execute(); | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } else if (attribute.relation === 'morphToOne') { | 
					
						
							|  |  |  |           // handled on the entry itself
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } else if (attribute.relation === 'morphToMany') { | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn, morphColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |           const { idColumn, typeColumn, typeField = '__type' } = morphColumn; | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           const rows = toAssocs(data[attributeName]).map((data) => ({ | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             [joinColumn.name]: id, | 
					
						
							|  |  |  |             [idColumn.name]: data.id, | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |             [typeColumn.name]: data[typeField], | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |             ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           })); | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           if (_.isEmpty(rows)) { | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           await this.createQueryBuilder(joinTable.name).insert(rows).execute(); | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |         if (attribute.joinColumn && attribute.owner) { | 
					
						
							| 
									
										
										
										
											2021-07-05 18:35:16 +02:00
										 |  |  |           if ( | 
					
						
							|  |  |  |             attribute.relation === 'oneToOne' && | 
					
						
							|  |  |  |             isBidirectional(attribute) && | 
					
						
							|  |  |  |             data[attributeName] | 
					
						
							|  |  |  |           ) { | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |             await this.createQueryBuilder(uid) | 
					
						
							| 
									
										
										
										
											2021-07-02 02:26:14 +02:00
										 |  |  |               .where({ [attribute.joinColumn.name]: data[attributeName], id: { $ne: id } }) | 
					
						
							|  |  |  |               .update({ [attribute.joinColumn.name]: null }) | 
					
						
							|  |  |  |               .execute(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // oneToOne oneToMany on the non owning side
 | 
					
						
							|  |  |  |         if (attribute.joinColumn && !attribute.owner) { | 
					
						
							|  |  |  |           // need to set the column on the target
 | 
					
						
							|  |  |  |           const { target } = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // TODO: check it is an id & the entity exists (will throw due to FKs otherwise so not a big pbl in SQL)
 | 
					
						
							| 
									
										
										
										
											2021-07-02 02:26:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |           await this.createQueryBuilder(target) | 
					
						
							|  |  |  |             .where({ [attribute.joinColumn.referencedColumn]: id }) | 
					
						
							|  |  |  |             .update({ [attribute.joinColumn.referencedColumn]: null }) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(target) | 
					
						
							|  |  |  |             .update({ [attribute.joinColumn.referencedColumn]: id }) | 
					
						
							|  |  |  |             // NOTE: works if it is an array or a single id
 | 
					
						
							|  |  |  |             .where({ id: data[attributeName] }) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.joinTable) { | 
					
						
							|  |  |  |           // need to set the column on the target
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn, inverseJoinColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |           if (isOneToAny(attribute) && isBidirectional(attribute)) { | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |             await this.createQueryBuilder(joinTable.name) | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               .delete() | 
					
						
							|  |  |  |               .where({ [inverseJoinColumn.name]: _.castArray(data[attributeName]) }) | 
					
						
							|  |  |  |               .where(joinTable.on || {}) | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |               .execute(); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           const insert = toAssocs(data[attributeName]).map((data) => { | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |             return { | 
					
						
							|  |  |  |               [joinColumn.name]: id, | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               [inverseJoinColumn.name]: data.id, | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |             }; | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // if there is nothing to insert
 | 
					
						
							|  |  |  |           if (insert.length === 0) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           await this.createQueryBuilder(joinTable.name).insert(insert).execute(); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Updates relations of an existing entity | 
					
						
							| 
									
										
										
										
											2021-06-30 21:17:32 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |      * @param {EntityManager} em - entity manager instance | 
					
						
							|  |  |  |      * @param {Metadata} metadata - model metadta | 
					
						
							|  |  |  |      * @param {ID} id - entity ID | 
					
						
							|  |  |  |      * @param {object} data - data received for creation | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     // TODO: check relation exists (handled by FKs except for polymorphics)
 | 
					
						
							| 
									
										
										
										
											2021-07-05 18:35:16 +02:00
										 |  |  |     // TODO: wrap Transaction
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |     async updateRelations(uid, id, data) { | 
					
						
							|  |  |  |       const { attributes } = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for (const attributeName in attributes) { | 
					
						
							|  |  |  |         const attribute = attributes[attributeName]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |         if (attribute.type !== 'relation' || !_.has(attributeName, data)) { | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.relation === 'morphOne' || attribute.relation === 'morphMany') { | 
					
						
							|  |  |  |           const { target, morphBy } = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const targetAttribute = db.metadata.get(target).attributes[morphBy]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (targetAttribute.relation === 'morphToOne') { | 
					
						
							|  |  |  |             // set columns
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = targetAttribute.morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await this.createQueryBuilder(target) | 
					
						
							|  |  |  |               .update({ [idColumn.name]: null, [typeColumn.name]: null }) | 
					
						
							|  |  |  |               .where({ [idColumn.name]: id, [typeColumn.name]: uid }) | 
					
						
							|  |  |  |               .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |             if (!_.isNull(data[attributeName])) { | 
					
						
							|  |  |  |               await this.createQueryBuilder(target) | 
					
						
							|  |  |  |                 .update({ [idColumn.name]: id, [typeColumn.name]: uid }) | 
					
						
							| 
									
										
										
										
											2021-07-30 21:15:58 +02:00
										 |  |  |                 .where({ id: toId(data[attributeName]) }) | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |                 .execute(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } else if (targetAttribute.relation === 'morphToMany') { | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             const { joinTable } = targetAttribute; | 
					
						
							|  |  |  |             const { joinColumn, morphColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |               .delete() | 
					
						
							|  |  |  |               .where({ | 
					
						
							|  |  |  |                 [idColumn.name]: id, | 
					
						
							|  |  |  |                 [typeColumn.name]: uid, | 
					
						
							|  |  |  |                 ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |                 field: attributeName, | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |               }) | 
					
						
							|  |  |  |               .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |             const rows = toAssocs(data[attributeName]).map((data, idx) => ({ | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               [joinColumn.name]: data.id, | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |               [idColumn.name]: id, | 
					
						
							|  |  |  |               [typeColumn.name]: uid, | 
					
						
							|  |  |  |               ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |               order: idx + 1, | 
					
						
							|  |  |  |               field: attributeName, | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (_.isEmpty(rows)) { | 
					
						
							|  |  |  |               continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |             await this.createQueryBuilder(joinTable.name).insert(rows).execute(); | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.relation === 'morphToOne') { | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |           // handled on the entry itself
 | 
					
						
							|  |  |  |           continue; | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.relation === 'morphToMany') { | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn, morphColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |           const { idColumn, typeColumn, typeField = '__type' } = morphColumn; | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |             .delete() | 
					
						
							|  |  |  |             .where({ | 
					
						
							|  |  |  |               [joinColumn.name]: id, | 
					
						
							|  |  |  |               ...(joinTable.on || {}), | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           const rows = toAssocs(data[attributeName]).map((data) => ({ | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             [joinColumn.name]: id, | 
					
						
							|  |  |  |             [idColumn.name]: data.id, | 
					
						
							| 
									
										
										
										
											2021-07-26 22:02:48 +02:00
										 |  |  |             [typeColumn.name]: data[typeField], | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |             ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |           })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (_.isEmpty(rows)) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |           await this.createQueryBuilder(joinTable.name).insert(rows).execute(); | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |         if (attribute.joinColumn && attribute.owner) { | 
					
						
							| 
									
										
										
										
											2022-05-19 14:47:23 +02:00
										 |  |  |           // handled in the row itself
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // oneToOne oneToMany on the non owning side.
 | 
					
						
							|  |  |  |         // Since it is a join column no need to remove previous relations
 | 
					
						
							|  |  |  |         if (attribute.joinColumn && !attribute.owner) { | 
					
						
							|  |  |  |           // need to set the column on the target
 | 
					
						
							|  |  |  |           const { target } = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |           await this.createQueryBuilder(target) | 
					
						
							|  |  |  |             .where({ [attribute.joinColumn.referencedColumn]: id }) | 
					
						
							|  |  |  |             .update({ [attribute.joinColumn.referencedColumn]: null }) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (!_.isNull(data[attributeName])) { | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |             await this.createQueryBuilder(target) | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               // NOTE: works if it is an array or a single id
 | 
					
						
							|  |  |  |               .where({ id: data[attributeName] }) | 
					
						
							|  |  |  |               .update({ [attribute.joinColumn.referencedColumn]: id }) | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |               .execute(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.joinTable) { | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn, inverseJoinColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |           // clear previous associations in the joinTable
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |             .delete() | 
					
						
							|  |  |  |             .where({ [joinColumn.name]: id }) | 
					
						
							|  |  |  |             .where(joinTable.on || {}) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-03 23:19:03 +02:00
										 |  |  |           if ( | 
					
						
							|  |  |  |             isBidirectional(attribute) && | 
					
						
							|  |  |  |             ['oneToOne', 'oneToMany'].includes(attribute.relation) | 
					
						
							|  |  |  |           ) { | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |             await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |               .delete() | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |               .where({ [inverseJoinColumn.name]: toIds(data[attributeName]) }) | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               .where(joinTable.on || {}) | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |               .execute(); | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |           if (!_.isNull(data[attributeName])) { | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |             const insert = toAssocs(data[attributeName]).map((data) => { | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               return { | 
					
						
							|  |  |  |                 [joinColumn.name]: id, | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |                 [inverseJoinColumn.name]: data.id, | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |                 ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |                 ...(data.__pivot || {}), | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |               }; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |             // if there is nothing to insert
 | 
					
						
							|  |  |  |             if (insert.length === 0) { | 
					
						
							|  |  |  |               continue; | 
					
						
							| 
									
										
										
										
											2021-07-02 02:26:14 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |             await this.createQueryBuilder(joinTable.name).insert(insert).execute(); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |      * Delete relational associations of an existing entity | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |      * This removes associations but doesn't do cascade deletions for components for example. This will be handled on the entity service layer instead | 
					
						
							| 
									
										
										
										
											2021-08-12 16:12:40 +02:00
										 |  |  |      * NOTE: Most of the deletion should be handled by ON DELETE CASCADE for dialects that have FKs | 
					
						
							| 
									
										
										
										
											2021-06-30 21:17:32 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |      * @param {EntityManager} em - entity manager instance | 
					
						
							|  |  |  |      * @param {Metadata} metadata - model metadta | 
					
						
							|  |  |  |      * @param {ID} id - entity ID | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-07-05 18:35:16 +02:00
										 |  |  |     // TODO: wrap Transaction
 | 
					
						
							| 
									
										
										
										
											2021-07-06 14:18:03 +02:00
										 |  |  |     async deleteRelations(uid, id) { | 
					
						
							|  |  |  |       const { attributes } = db.metadata.get(uid); | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for (const attributeName in attributes) { | 
					
						
							|  |  |  |         const attribute = attributes[attributeName]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |         if (attribute.type !== 'relation') { | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |           if morphOne | morphMany | 
					
						
							|  |  |  |             if morphBy is morphToOne | 
					
						
							|  |  |  |               set null | 
					
						
							|  |  |  |             if morphBy is morphToOne | 
					
						
							|  |  |  |               delete links | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         if (attribute.relation === 'morphOne' || attribute.relation === 'morphMany') { | 
					
						
							|  |  |  |           const { target, morphBy } = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const targetAttribute = db.metadata.get(target).attributes[morphBy]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if (targetAttribute.relation === 'morphToOne') { | 
					
						
							|  |  |  |             // set columns
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = targetAttribute.morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await this.createQueryBuilder(target) | 
					
						
							|  |  |  |               .update({ [idColumn.name]: null, [typeColumn.name]: null }) | 
					
						
							|  |  |  |               .where({ [idColumn.name]: id, [typeColumn.name]: uid }) | 
					
						
							|  |  |  |               .execute(); | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  |           } else if (targetAttribute.relation === 'morphToMany') { | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |             const { joinTable } = targetAttribute; | 
					
						
							|  |  |  |             const { morphColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const { idColumn, typeColumn } = morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |               .delete() | 
					
						
							|  |  |  |               .where({ | 
					
						
							|  |  |  |                 [idColumn.name]: id, | 
					
						
							|  |  |  |                 [typeColumn.name]: uid, | 
					
						
							|  |  |  |                 ...(joinTable.on || {}), | 
					
						
							| 
									
										
										
										
											2021-08-17 18:08:42 +02:00
										 |  |  |                 field: attributeName, | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |               }) | 
					
						
							|  |  |  |               .execute(); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |           if morphToOne | 
					
						
							|  |  |  |             nothing to do | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         if (attribute.relation === 'morphToOne') { | 
					
						
							|  |  |  |           // do nothing
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |             if morphToMany | 
					
						
							|  |  |  |             delete links | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         if (attribute.relation === 'morphToMany') { | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |             .delete() | 
					
						
							|  |  |  |             .where({ | 
					
						
							|  |  |  |               [joinColumn.name]: id, | 
					
						
							|  |  |  |               ...(joinTable.on || {}), | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             .execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |         // do not need to delete links when using foreign keys
 | 
					
						
							| 
									
										
										
										
											2021-07-26 19:40:30 +02:00
										 |  |  |         if (db.dialect.usesForeignKeys()) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |         // NOTE: we do not remove existing associations with the target as it should handled by unique FKs instead
 | 
					
						
							|  |  |  |         if (attribute.joinColumn && attribute.owner) { | 
					
						
							|  |  |  |           // nothing to do => relation already added on the table
 | 
					
						
							|  |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // oneToOne oneToMany on the non owning side.
 | 
					
						
							|  |  |  |         if (attribute.joinColumn && !attribute.owner) { | 
					
						
							|  |  |  |           // need to set the column on the target
 | 
					
						
							|  |  |  |           const { target } = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(target) | 
					
						
							|  |  |  |             .where({ [attribute.joinColumn.referencedColumn]: id }) | 
					
						
							| 
									
										
										
										
											2021-07-02 02:26:14 +02:00
										 |  |  |             .update({ [attribute.joinColumn.referencedColumn]: null }) | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |             .execute(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (attribute.joinTable) { | 
					
						
							|  |  |  |           const { joinTable } = attribute; | 
					
						
							|  |  |  |           const { joinColumn } = joinTable; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           await this.createQueryBuilder(joinTable.name) | 
					
						
							|  |  |  |             .delete() | 
					
						
							|  |  |  |             .where({ [joinColumn.name]: id }) | 
					
						
							| 
									
										
										
										
											2021-07-28 15:32:21 +02:00
										 |  |  |             .where(joinTable.on || {}) | 
					
						
							| 
									
										
										
										
											2021-06-28 12:34:29 +02:00
										 |  |  |             .execute(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |     // TODO: support multiple relations at once with the populate syntax
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |     // TODO: add lifecycle events
 | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |     async populate(uid, entity, populate) { | 
					
						
							|  |  |  |       const entry = await this.findOne(uid, { | 
					
						
							|  |  |  |         select: ['id'], | 
					
						
							|  |  |  |         where: { id: entity.id }, | 
					
						
							| 
									
										
										
										
											2021-09-13 12:03:12 +02:00
										 |  |  |         populate, | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 15:50:34 +02:00
										 |  |  |       return { ...entity, ...entry }; | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |     // TODO: support multiple relations at once with the populate syntax
 | 
					
						
							| 
									
										
										
										
											2021-08-03 11:22:57 +02:00
										 |  |  |     // TODO: add lifecycle events
 | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |     async load(uid, entity, field, params) { | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |       const { attributes } = db.metadata.get(uid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const attribute = attributes[field]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!attribute || attribute.type !== 'relation') { | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |         throw new Error('Invalid load. Expected a relational attribute'); | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const entry = await this.findOne(uid, { | 
					
						
							|  |  |  |         select: ['id'], | 
					
						
							| 
									
										
										
										
											2021-07-08 18:15:32 +02:00
										 |  |  |         where: { id: entity.id }, | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |         populate: { | 
					
						
							|  |  |  |           [field]: params || true, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-10 15:51:38 +02:00
										 |  |  |       if (!entry) { | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-07 18:04:39 +02:00
										 |  |  |       return entry[field]; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     // cascading
 | 
					
						
							|  |  |  |     // aggregations
 | 
					
						
							|  |  |  |     // -> avg
 | 
					
						
							|  |  |  |     // -> min
 | 
					
						
							|  |  |  |     // -> max
 | 
					
						
							|  |  |  |     // -> grouping
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // formulas
 | 
					
						
							|  |  |  |     // custom queries
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // utilities
 | 
					
						
							|  |  |  |     // -> map result
 | 
					
						
							|  |  |  |     // -> map input
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // extra features
 | 
					
						
							|  |  |  |     // -> virtuals
 | 
					
						
							|  |  |  |     // -> private
 | 
					
						
							| 
									
										
										
										
											2021-06-30 21:17:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     createQueryBuilder(uid) { | 
					
						
							|  |  |  |       return createQueryBuilder(uid, db); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getRepository(uid) { | 
					
						
							|  |  |  |       if (!repoMap[uid]) { | 
					
						
							|  |  |  |         repoMap[uid] = createRepository(uid, db); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return repoMap[uid]; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     clearRepositories() { | 
					
						
							|  |  |  |       repoMap.clear(); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = { | 
					
						
							|  |  |  |   createEntityManager, | 
					
						
							|  |  |  | }; |