@reldens/storage 0.87.0 → 0.89.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.claude/driver-methods-complete-analysis.md +1978 -0
  2. package/.claude/test-architecture.md +973 -0
  3. package/CLAUDE.md +141 -7
  4. package/README.md +14 -2
  5. package/bin/reldens-storage.js +1 -1
  6. package/lib/base-driver.js +8 -0
  7. package/lib/entities-generator.js +1 -3
  8. package/lib/entity-templates/mikro-orm-model.template +2 -1
  9. package/lib/generators/models-generation.js +126 -5
  10. package/lib/mikro-orm/mikro-orm-data-server.js +24 -10
  11. package/lib/mikro-orm/mikro-orm-driver.js +184 -116
  12. package/lib/objection-js/objection-js-driver.js +111 -19
  13. package/lib/prisma/prisma-client-loader.js +4 -0
  14. package/lib/prisma/prisma-data-server.js +3 -2
  15. package/lib/prisma/prisma-driver.js +12 -10
  16. package/lib/prisma/prisma-filter-processor.js +193 -146
  17. package/lib/prisma/prisma-metadata-loader.js +0 -4
  18. package/lib/prisma/prisma-relation-resolver.js +292 -267
  19. package/lib/prisma/prisma-type-caster.js +280 -260
  20. package/package.json +15 -6
  21. package/tests/.env.test.example +7 -0
  22. package/tests/fixtures/categories-fixtures.js +164 -0
  23. package/tests/fixtures/expected-entities-mikro-orm/entities/test-categories-entity.js +70 -0
  24. package/tests/fixtures/expected-entities-mikro-orm/entities/test-products-entity.js +95 -0
  25. package/tests/fixtures/expected-entities-mikro-orm/entities/test-reviews-entity.js +84 -0
  26. package/tests/fixtures/expected-entities-mikro-orm/entities-config.js +17 -0
  27. package/tests/fixtures/expected-entities-mikro-orm/entities-translations.js +13 -0
  28. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/registered-models-mikro-orm.js +23 -0
  29. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +57 -0
  30. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +79 -0
  31. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +70 -0
  32. package/tests/fixtures/expected-entities-objection-js/entities/test-categories-entity.js +70 -0
  33. package/tests/fixtures/expected-entities-objection-js/entities/test-products-entity.js +95 -0
  34. package/tests/fixtures/expected-entities-objection-js/entities/test-reviews-entity.js +84 -0
  35. package/tests/fixtures/expected-entities-objection-js/entities-config.js +17 -0
  36. package/tests/fixtures/expected-entities-objection-js/entities-translations.js +13 -0
  37. package/tests/fixtures/expected-entities-objection-js/models/objection-js/registered-models-objection-js.js +23 -0
  38. package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-categories-model.js +33 -0
  39. package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-products-model.js +42 -0
  40. package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-reviews-model.js +33 -0
  41. package/tests/fixtures/expected-entities-prisma/entities/test-categories-entity.js +70 -0
  42. package/tests/fixtures/expected-entities-prisma/entities/test-products-entity.js +95 -0
  43. package/tests/fixtures/expected-entities-prisma/entities/test-reviews-entity.js +84 -0
  44. package/tests/fixtures/expected-entities-prisma/entities-config.js +17 -0
  45. package/tests/fixtures/expected-entities-prisma/entities-translations.js +13 -0
  46. package/tests/fixtures/expected-entities-prisma/models/prisma/registered-models-prisma.js +23 -0
  47. package/tests/fixtures/expected-entities-prisma/models/prisma/test-categories-model.js +43 -0
  48. package/tests/fixtures/expected-entities-prisma/models/prisma/test-products-model.js +50 -0
  49. package/tests/fixtures/expected-entities-prisma/models/prisma/test-reviews-model.js +46 -0
  50. package/tests/fixtures/products-fixtures.js +119 -0
  51. package/tests/fixtures/reviews-fixtures.js +42 -0
  52. package/tests/fixtures/sql/test-schema.sql +59 -0
  53. package/tests/integration/test-drivers.js +257 -0
  54. package/tests/integration/test-nested-filters.js +408 -0
  55. package/tests/integration/test-relations.js +349 -0
  56. package/tests/run-tests.js +213 -0
  57. package/tests/unit/test-drivers.js +89 -0
  58. package/tests/unit/test-entities-generator.js +533 -0
  59. package/tests/unit/test-entity-manager.js +128 -0
  60. package/tests/unit/test-type-mapper.js +232 -0
  61. package/tests/utils/custom-reporter.js +73 -0
  62. package/tests/utils/driver-registry.js +144 -0
  63. package/tests/utils/prisma-subprocess-worker.js +150 -0
  64. package/tests/utils/test-helpers.js +726 -0
  65. package/tests/utils/test-runner.js +63 -0
@@ -6,6 +6,7 @@
6
6
 
7
7
  const { BaseDriver } = require('../base-driver');
8
8
  const { Logger, sc } = require('@reldens/utils');
9
+ const { Collection } = require('@mikro-orm/core');
9
10
 
10
11
  class MikroOrmDriver extends BaseDriver
11
12
  {
@@ -27,7 +28,19 @@ class MikroOrmDriver extends BaseDriver
27
28
  }
28
29
  this.orm = props.orm;
29
30
  this.server = props.server;
30
- this.repository = this.orm.em.getRepository(this.rawModel);
31
+ this.entitySchema = (sc.isObject(this.rawModel) && sc.hasOwn(this.rawModel, 'schema')) ? this.rawModel.schema : this.rawModel;
32
+ this.repository = this.orm.em.getRepository(this.entitySchema);
33
+ this.mikroOrmOperators = {
34
+ 'GT': '$gt',
35
+ 'GTE': '$gte',
36
+ 'LT': '$lt',
37
+ 'LTE': '$lte',
38
+ 'NE': '$ne',
39
+ 'NOT': '$ne',
40
+ 'IN': '$in',
41
+ 'NOT IN': '$nin'
42
+ };
43
+ this.fkMappings = this.rawModel._fkMappings || this.entitySchema._fkMappings || {};
31
44
  }
32
45
 
33
46
  databaseName()
@@ -37,17 +50,17 @@ class MikroOrmDriver extends BaseDriver
37
50
 
38
51
  id()
39
52
  {
40
- return this.rawModel.entity.name || this.name();
53
+ return (this.rawModel.entity || this.rawModel).name || this.name();
41
54
  }
42
55
 
43
56
  name()
44
57
  {
45
- return this.rawModel.entity.name || this.config.dbName;
58
+ return (this.rawModel.entity || this.rawModel).name || this.config.dbName;
46
59
  }
47
60
 
48
61
  tableName()
49
62
  {
50
- return this.rawModel.entity.name;
63
+ return (this.rawModel.entity || this.rawModel).name;
51
64
  }
52
65
 
53
66
  property(propertyName)
@@ -57,16 +70,25 @@ class MikroOrmDriver extends BaseDriver
57
70
 
58
71
  getAllRelations()
59
72
  {
60
- if('function' !== typeof this.rawModel.entity.relationMappings){
73
+ if(!this.entitySchema.meta || !this.entitySchema.meta.properties){
61
74
  return [];
62
75
  }
63
- return Object.keys(this.rawModel.entity.relationMappings() || {});
76
+ let relations = [];
77
+ for(let propName of Object.keys(this.entitySchema.meta.properties)){
78
+ let prop = this.entitySchema.meta.properties[propName];
79
+ if(prop.kind === 'm:1' || prop.kind === '1:m' || prop.kind === 'm:n'){
80
+ relations.push(propName);
81
+ }
82
+ }
83
+ return relations;
64
84
  }
65
85
 
66
86
  async create(params)
67
87
  {
68
- let newInstance = await this.orm.em.create(this.rawModel, params);
88
+ let transformed = this.transformFkToRelations(params);
89
+ let newInstance = await this.orm.em.create(this.entitySchema, transformed);
69
90
  await this.orm.em.upsert(newInstance);
91
+ await this.orm.em.flush();
70
92
  return newInstance;
71
93
  }
72
94
 
@@ -80,53 +102,61 @@ class MikroOrmDriver extends BaseDriver
80
102
  return await this.appendRelationsToCollection(newInstance, relations);
81
103
  }
82
104
 
83
- async update(filters, updatePatch)
105
+ async applyUpdateToEntities(processedFilters, updatePatch)
84
106
  {
85
- let processedFilters = this.processFilters(filters);
86
107
  let entities = await this.repository.find(processedFilters, this.queryBuilder(true, true, true));
87
108
  if(0 === entities.length){
88
109
  return false;
89
110
  }
111
+ let transformed = this.transformFkToRelations(updatePatch);
90
112
  for(let entity of entities){
91
- Object.assign(entity, updatePatch);
113
+ Object.assign(entity, transformed);
92
114
  await this.orm.em.upsert(entity);
93
115
  await this.orm.em.flush();
94
116
  }
95
117
  return entities;
96
118
  }
97
119
 
120
+ async update(filters, updatePatch)
121
+ {
122
+ let processedFilters = this.processFilters(filters);
123
+ return this.applyUpdateToEntities(processedFilters, updatePatch);
124
+ }
125
+
98
126
  async updateBy(field, fieldValue, updatePatch, operator = null)
99
127
  {
100
128
  let filter = this.createSingleFilter(field, fieldValue, operator);
101
129
  let processedFilters = this.processFilters(filter);
102
- let entities = await this.repository.find(processedFilters, this.queryBuilder(true, true, true));
103
- if(0 === entities.length){
104
- return false;
105
- }
106
- for(let entity of entities){
107
- Object.assign(entity, updatePatch);
108
- await this.orm.em.upsert(entity);
109
- await this.orm.em.flush();
110
- }
111
- return entities;
130
+ return this.applyUpdateToEntities(processedFilters, updatePatch);
112
131
  }
113
132
 
114
- updateById(id, params)
133
+ async updateById(id, params)
115
134
  {
116
- return this.update({id}, params);
135
+ let entities = await this.update({id}, params);
136
+ if(!entities){
137
+ return false;
138
+ }
139
+ if(1 < entities.length){
140
+ Logger.warning('Multiple entities updated by ID: '+entities.map(e => e.id).join(', '));
141
+ }
142
+ return entities.shift();
117
143
  }
118
144
 
119
145
  async upsert(params, filters)
120
146
  {
121
147
  if(params.id){
122
- let patch = Object.assign({}, params);
123
- delete patch.id;
124
- return this.updateById(params.id, patch);
148
+ let existent = await this.loadById(params.id);
149
+ if(existent){
150
+ let patch = Object.assign({}, params);
151
+ delete patch.id;
152
+ return this.updateById(params.id, patch);
153
+ }
125
154
  }
126
155
  if(filters){
127
156
  let existent = await this.loadOne(filters);
128
157
  if(existent){
129
- return this.updateById(existent.id, params);
158
+ let transformed = this.transformFkToRelations(params);
159
+ return this.updateById(existent.id, transformed);
130
160
  }
131
161
  }
132
162
  return this.create(params);
@@ -136,17 +166,25 @@ class MikroOrmDriver extends BaseDriver
136
166
  {
137
167
  let processedFilters = this.processFilters(filters);
138
168
  let entries = await this.repository.find(processedFilters);
139
- if(!entries){
169
+ if(!entries || 0 === entries.length){
140
170
  return false;
141
171
  }
142
172
  for(let entry of entries){
143
- await this.repository.nativeDelete(entry.id);
173
+ await this.orm.em.remove(entry);
144
174
  }
175
+ await this.orm.em.flush();
176
+ return true;
145
177
  }
146
178
 
147
- deleteById(id)
179
+ async deleteById(id)
148
180
  {
149
- return this.repository.nativeDelete(id);
181
+ let entity = await this.loadById(id);
182
+ if(!entity){
183
+ return false;
184
+ }
185
+ await this.orm.em.remove(entity);
186
+ await this.orm.em.flush();
187
+ return true;
150
188
  }
151
189
 
152
190
  async count(filters)
@@ -161,31 +199,30 @@ class MikroOrmDriver extends BaseDriver
161
199
  relations = this.getAllRelations();
162
200
  }
163
201
  let processedFilters = this.processFilters(filters);
164
- if(0 === relations.length || 'function' !== typeof this.rawModel.entity.relationMappings){
202
+ if(0 === relations.length || !this.entitySchema.meta || !this.entitySchema.meta.properties){
165
203
  return this.repository.count(processedFilters);
166
204
  }
167
- let queryBuilder = this.orm.em.createQueryBuilder(this.rawModel);
168
- let relationMappings = this.rawModel.entity.relationMappings();
205
+ let queryBuilder = this.orm.em.createQueryBuilder(this.entitySchema);
206
+ let properties = this.entitySchema.meta.properties;
169
207
  let aliasCounter = 0;
170
208
  for(let relationName of relations){
171
- let relation = relationMappings[relationName];
172
- if(!relation){
209
+ let prop = properties[relationName];
210
+ if(!prop || !prop.kind || (prop.kind !== 'm:1' && prop.kind !== '1:m')){
173
211
  continue;
174
212
  }
175
- let relationEntity = this.server.entityManager.get(relation.entityName);
176
- if(!relationEntity || !relationEntity.rawModel){
213
+ let relationDriver = this.server.entityManager.get(prop.entity);
214
+ if(!relationDriver || !relationDriver.entitySchema){
177
215
  continue;
178
216
  }
179
217
  let alias = 'rel_'+aliasCounter;
180
- let joinField = relation.join.from;
181
- let targetField = relation.join.to;
182
- let isManyToOne = 'm:1' === relation.reference;
183
- let isOneToMany = '1:m' === relation.reference;
184
- if(isManyToOne){
185
- queryBuilder.leftJoin(relationEntity.rawModel, alias, 'e.'+joinField+' = '+alias+'.'+targetField);
218
+ if('m:1' === prop.kind && prop.joinColumn){
219
+ queryBuilder.leftJoin(relationName, alias, 'e.'+prop.joinColumn+' = '+alias+'.id');
186
220
  }
187
- if(isOneToMany){
188
- queryBuilder.leftJoin(relationEntity.rawModel, alias, 'e.'+joinField+' = '+alias+'.'+targetField);
221
+ if('1:m' === prop.kind && prop.mappedBy){
222
+ let mappedProp = relationDriver.entitySchema.meta.properties[prop.mappedBy];
223
+ if(mappedProp && mappedProp.joinColumn){
224
+ queryBuilder.leftJoin(relationName, alias, 'e.id = '+alias+'.'+mappedProp.joinColumn);
225
+ }
189
226
  }
190
227
  aliasCounter++;
191
228
  }
@@ -245,7 +282,7 @@ class MikroOrmDriver extends BaseDriver
245
282
 
246
283
  loadById(id)
247
284
  {
248
- return this.loadBy('id', id);
285
+ return this.loadOneBy('id', id);
249
286
  }
250
287
 
251
288
  async loadByIdWithRelations(id, relations)
@@ -253,7 +290,7 @@ class MikroOrmDriver extends BaseDriver
253
290
  if(!sc.isArray(relations) || 0 === relations.length){
254
291
  relations = this.getAllRelations();
255
292
  }
256
- let entity = await this.loadBy('id', id);
293
+ let entity = await this.loadOneBy('id', id);
257
294
  return await this.appendRelationsToCollection(entity, relations);
258
295
  }
259
296
 
@@ -305,6 +342,10 @@ class MikroOrmDriver extends BaseDriver
305
342
  let processedFilters = {};
306
343
  for(let key of Object.keys(filters)){
307
344
  let value = filters[key];
345
+ if('AND' === key && sc.isArray(value)){
346
+ processedFilters.$and = value.map(condition => this.processFilters(condition));
347
+ continue;
348
+ }
308
349
  if('OR' === key && sc.isArray(value)){
309
350
  processedFilters.$or = value.map(condition => this.processFilters(condition));
310
351
  continue;
@@ -328,26 +369,22 @@ class MikroOrmDriver extends BaseDriver
328
369
  if('LIKE' === upperOperator){
329
370
  return this.handleLikeOperator(value, fieldName);
330
371
  }
331
- let operatorsMap = {
332
- '=': value,
333
- '!=': {$ne: value},
334
- '>': {$gt: value},
335
- '>=': {$gte: value},
336
- '<': {$lt: value},
337
- '<=': {$lte: value},
338
- 'IN': {$in: value},
339
- 'NOT IN': {$nin: value}
340
- };
341
- return operatorsMap[upperOperator] || value;
372
+ if('EQ' === upperOperator){
373
+ return value;
374
+ }
375
+ if(sc.hasOwn(this.mikroOrmOperators, upperOperator)){
376
+ return {[this.mikroOrmOperators[upperOperator]]: value};
377
+ }
378
+ return value;
342
379
  }
343
380
 
344
381
  handleLikeOperator(value, fieldName)
345
382
  {
346
383
  let cleanValue = String(value).replace(/%/g, '');
347
384
  if(this.isJsonField(fieldName)){
348
- return {$like: '%' + cleanValue + '%'};
385
+ return {$like: '%'+cleanValue+'%'};
349
386
  }
350
- return {$like: '%' + cleanValue + '%'};
387
+ return {$like: '%'+cleanValue+'%'};
351
388
  }
352
389
 
353
390
  queryBuilder(useLimit = false, useOffset = false, useSort = false)
@@ -362,7 +399,7 @@ class MikroOrmDriver extends BaseDriver
362
399
  if(useOffset && 0 !== this.offset){
363
400
  queryBuilder.offset = this.offset;
364
401
  }
365
- if(useSort && false !== this.sortBy && false !== this.sortDirection){
402
+ if(useSort && this.sortBy && this.sortDirection){
366
403
  queryBuilder.orderBy = {
367
404
  [this.sortBy]: this.sortDirection,
368
405
  };
@@ -381,99 +418,130 @@ class MikroOrmDriver extends BaseDriver
381
418
  return filter;
382
419
  }
383
420
 
384
- async appendRelationsToCollection(entitiesCollection, relations)
421
+ convertCollectionsToArrays(entity)
385
422
  {
386
- if('function' !== typeof this.rawModel.entity.relationMappings){
387
- return entitiesCollection;
388
- }
389
- if(!sc.isArray(relations) || 0 === relations.length){
390
- relations = this.getAllRelations();
391
- }
392
- if(0 === relations.length){
393
- return entitiesCollection;
423
+ if(!entity){
424
+ return entity;
394
425
  }
395
- if(sc.isArray(entitiesCollection)){
396
- for(let entity of entitiesCollection){
397
- await this.appendRelatedEntities(entity, relations);
426
+ for(let key of Object.keys(entity)){
427
+ if(entity[key] && entity[key] instanceof Collection){
428
+ entity[key] = entity[key].getItems();
398
429
  }
399
430
  }
400
- if(!sc.isArray(entitiesCollection)){
401
- await this.appendRelatedEntities(entitiesCollection, relations);
402
- }
403
- return entitiesCollection;
431
+ return entity;
404
432
  }
405
433
 
406
- async appendRelatedEntities(entity, relations)
434
+ addFkFieldsFromRelations(entity)
407
435
  {
408
- if('function' !== typeof this.rawModel.entity.relationMappings){
436
+ if(!entity){
409
437
  return entity;
410
438
  }
411
- let relationMappings = this.rawModel.entity.relationMappings();
412
- for(let i of relations){
413
- let relation = relationMappings[i];
414
- let relationRepository = this.server.getEntity(relation.entityName);
415
- let isManyToOne = 'm:1' === relation.reference;
416
- let isOneToMany = '1:m' === relation.reference;
417
- if(isManyToOne){
418
- entity[i] = await relationRepository.loadOneBy(relation.join.to, entity[relation.join.from]);
439
+ for(let fkColumn of Object.keys(this.fkMappings)){
440
+ let mapping = this.fkMappings[fkColumn];
441
+ let relation = entity[mapping.relationKey];
442
+ if(!relation){
443
+ continue;
444
+ }
445
+ if(sc.hasOwn(relation, mapping.referencedColumn)){
446
+ entity[fkColumn] = relation[mapping.referencedColumn];
447
+ continue;
419
448
  }
420
- if(isOneToMany){
421
- entity[i] = await relationRepository.loadBy(relation.join.to, entity[relation.join.from]);
449
+ if(sc.hasOwn(relation, 'id')){
450
+ entity[fkColumn] = relation.id;
422
451
  }
423
452
  }
424
453
  return entity;
425
454
  }
426
455
 
456
+ async appendRelationsToCollection(entitiesCollection, relations)
457
+ {
458
+ if(!relations || 0 === relations.length){
459
+ return entitiesCollection;
460
+ }
461
+ if(!entitiesCollection){
462
+ return entitiesCollection;
463
+ }
464
+ await this.orm.em.populate(entitiesCollection, relations);
465
+ if(sc.isArray(entitiesCollection)){
466
+ for(let entity of entitiesCollection){
467
+ this.convertCollectionsToArrays(entity);
468
+ }
469
+ return entitiesCollection;
470
+ }
471
+ return this.convertCollectionsToArrays(entitiesCollection);
472
+ }
473
+
427
474
  async createNested(newInstance, params, relations)
428
475
  {
429
- if('function' !== typeof this.rawModel.entity.relationMappings){
476
+ if(!this.entitySchema.meta || !this.entitySchema.meta.properties){
430
477
  return false;
431
478
  }
432
- let relationMappings = this.rawModel.entity.relationMappings();
433
- for(let i of Object.keys(relationMappings)){
434
- if(sc.isArray(relations) && 0 < relations.length && -1 === relations.indexOf(i)){
479
+ let properties = this.entitySchema.meta.properties;
480
+ for(let relationName of Object.keys(properties)){
481
+ let prop = properties[relationName];
482
+ if(!prop.kind || (prop.kind !== 'm:1' && prop.kind !== '1:m')){
435
483
  continue;
436
484
  }
437
- let relation = relationMappings[i];
438
- let relationEntity = this.server.entityManager.get(relation.entityName).rawModel.entity;
439
- if(!relationEntity){
440
- Logger.warning('Factory not found for relation definition:', relation);
485
+ if(sc.isArray(relations) && 0 < relations.length && -1 === relations.indexOf(relationName)){
441
486
  continue;
442
487
  }
443
- let isArray = sc.isArray(params);
444
- if(!isArray){
445
- if(!sc.hasOwn(params, relation.join.from) || !params[relation.join.from]){
446
- continue;
447
- }
448
- await this.createOne(params, i, relationEntity, newInstance, relation);
488
+ let relationDriver = this.server.entityManager.get(prop.entity);
489
+ if(!relationDriver){
490
+ Logger.warning('Entity not found for relation:', prop.entity);
491
+ continue;
492
+ }
493
+ let isOneToMany = '1:m' === prop.kind;
494
+ let isManyToOne = 'm:1' === prop.kind;
495
+ if(isManyToOne && sc.hasOwn(params, relationName)){
496
+ await this.createOne(params, relationName, relationDriver, newInstance, prop);
449
497
  continue;
450
498
  }
451
- if(isArray){
452
- await this.createMany(params, i, relationEntity, newInstance, relation);
499
+ if(isOneToMany && sc.hasOwn(params, relationName) && sc.isArray(params[relationName])){
500
+ await this.createMany(params, relationName, relationDriver, newInstance, prop);
453
501
  }
454
502
  }
455
503
  }
456
504
 
457
- async createOne(params, i, relationEntity, newInstance, relation)
505
+ async createOne(params, relationName, relationDriver, newInstance, prop)
458
506
  {
459
- params[i] = newInstance[relation.join.from];
460
- let nestedObject = relationEntity.createByProps(params[i]);
461
- await this.repository.persist(nestedObject).flush();
507
+ let nestedData = params[relationName];
508
+ if(prop.joinColumn){
509
+ nestedData[prop.joinColumn] = newInstance.id;
510
+ }
511
+ let nestedObject = await relationDriver.create(nestedData);
462
512
  await this.orm.em.flush();
463
- newInstance[i] = nestedObject;
513
+ newInstance[relationName] = nestedObject;
464
514
  }
465
515
 
466
- async createMany(params, i, relationEntity, newInstance, relation)
516
+ async createMany(params, relationName, relationDriver, newInstance, prop)
467
517
  {
468
518
  let nestedArray = [];
469
- for(let objectData of params[i]){
470
- objectData[relation.join.to] = newInstance[relation.join.from];
471
- let nestedObject = relationEntity.createByProps(objectData);
472
- await this.repository.persist(nestedObject).flush();
519
+ for(let objectData of params[relationName]){
520
+ if(prop.joinColumn){
521
+ objectData[prop.joinColumn] = newInstance.id;
522
+ }
523
+ let nestedObject = await relationDriver.create(objectData);
473
524
  await this.orm.em.flush();
474
525
  nestedArray.push(nestedObject);
475
526
  }
476
- newInstance[i] = nestedArray;
527
+ newInstance[relationName] = nestedArray;
528
+ }
529
+
530
+ transformFkToRelations(params)
531
+ {
532
+ if(!params || 'object' !== typeof params){
533
+ return params;
534
+ }
535
+ let transformed = {...params};
536
+ for(let fkColumn of Object.keys(this.fkMappings)){
537
+ if(!sc.hasOwn(params, fkColumn) || null === params[fkColumn]){
538
+ continue;
539
+ }
540
+ let mapping = this.fkMappings[fkColumn];
541
+ transformed[mapping.relationKey] = this.orm.em.getReference(mapping.entityName, params[fkColumn]);
542
+ delete transformed[fkColumn];
543
+ }
544
+ return transformed;
477
545
  }
478
546
 
479
547
  }