@reldens/storage 0.115.0 → 0.117.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.
- package/lib/generators/models-generation.js +7 -20
- package/lib/mikro-orm/mikro-orm-driver.js +71 -16
- package/package.json +5 -5
- package/tests/fixtures/expected-entities/entities/test-product-details-entity.js +63 -0
- package/tests/fixtures/expected-entities/entities-config.js +6 -4
- package/tests/fixtures/expected-entities/entities-translations.js +23 -14
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/registered-models-mikro-orm.js +2 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js +60 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +5 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/registered-models-objection-js.js +2 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-product-details-model.js +33 -0
- package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-products-model.js +9 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/registered-models-prisma.js +2 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-product-details-model.js +41 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-products-model.js +2 -0
- package/tests/fixtures/product-details-fixtures.js +19 -0
- package/tests/fixtures/sql/test-schema.sql +13 -0
- package/tests/integration/test-relations.js +64 -0
- package/tests/run-tests.js +6 -0
- package/tests/unit/test-models-generation.js +164 -0
- package/tests/utils/driver-registry.js +1 -1
- package/tests/utils/test-helpers.js +12 -9
|
@@ -346,7 +346,7 @@ class ModelsGeneration extends BaseGenerator
|
|
|
346
346
|
continue;
|
|
347
347
|
}
|
|
348
348
|
let relationKey = this.generateForwardRelationKey(column.referencedTable, columnName, referenceCounts);
|
|
349
|
-
let relationType = this.
|
|
349
|
+
let relationType = this.determineRelationType(column, true);
|
|
350
350
|
relations[relationKey] = {
|
|
351
351
|
fromColumn: columnName,
|
|
352
352
|
toColumn: column.referencedColumn,
|
|
@@ -375,7 +375,7 @@ class ModelsGeneration extends BaseGenerator
|
|
|
375
375
|
continue;
|
|
376
376
|
}
|
|
377
377
|
let relationKey = this.generateReverseRelationKey(otherTableName, columnName, referenceCounts);
|
|
378
|
-
let relationType = this.
|
|
378
|
+
let relationType = this.determineRelationType(column, false);
|
|
379
379
|
reverseRelations[relationKey] = {
|
|
380
380
|
fromColumn: column.referencedColumn,
|
|
381
381
|
toColumn: columnName,
|
|
@@ -442,25 +442,12 @@ class ModelsGeneration extends BaseGenerator
|
|
|
442
442
|
return RELATION_PREFIX+referencingTable+'_'+columnSuffix;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
-
|
|
445
|
+
determineMikroOrmForwardKind(column)
|
|
446
446
|
{
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
determineReverseRelationType(referencingTableName, referencingColumnName, referencingColumn)
|
|
451
|
-
{
|
|
452
|
-
if(!this.allTablesData[referencingTableName]){
|
|
453
|
-
return 'HasManyRelation';
|
|
454
|
-
}
|
|
455
|
-
let referencingTableData = this.allTablesData[referencingTableName];
|
|
456
|
-
let referencingColumnData = referencingTableData.columns[referencingColumnName];
|
|
457
|
-
if(!referencingColumnData){
|
|
458
|
-
return 'HasManyRelation';
|
|
447
|
+
if('HasOneRelation' === this.determineRelationType(column, false)){
|
|
448
|
+
return this.mikroOrmRelationKindMap.HasOneRelation;
|
|
459
449
|
}
|
|
460
|
-
|
|
461
|
-
return 'HasOneRelation';
|
|
462
|
-
}
|
|
463
|
-
return 'HasManyRelation';
|
|
450
|
+
return this.mikroOrmRelationKindMap.BelongsToOneRelation;
|
|
464
451
|
}
|
|
465
452
|
|
|
466
453
|
determineRelationType(column, isForwardRelation)
|
|
@@ -529,7 +516,7 @@ class ModelsGeneration extends BaseGenerator
|
|
|
529
516
|
let relation = relations[relationKey];
|
|
530
517
|
let relatedModelClass = sc.capitalizedCamelCase(relation.referencedTable)+'Model';
|
|
531
518
|
let relatedModelFile = sc.kebabCase(relation.referencedTable)+'-model';
|
|
532
|
-
let kind =
|
|
519
|
+
let kind = this.determineMikroOrmForwardKind(columns[relation.fromColumn]);
|
|
533
520
|
let propDef = relationKey+': {\n';
|
|
534
521
|
propDef += ' kind: \''+kind+'\',\n';
|
|
535
522
|
propDef += ' entity: () => require(\'./'+relatedModelFile+'\').'+relatedModelClass;
|
|
@@ -76,13 +76,64 @@ class MikroOrmDriver extends BaseDriver
|
|
|
76
76
|
let relations = [];
|
|
77
77
|
for(let propName of Object.keys(this.entitySchema.meta.properties)){
|
|
78
78
|
let prop = this.entitySchema.meta.properties[propName];
|
|
79
|
-
if(prop.kind
|
|
79
|
+
if('m:1' === prop.kind || '1:1' === prop.kind || '1:m' === prop.kind || 'm:n' === prop.kind){
|
|
80
80
|
relations.push(propName);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
return relations;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
isOwningRelation(prop)
|
|
87
|
+
{
|
|
88
|
+
if('m:1' === prop.kind){
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return '1:1' === prop.kind && Boolean(prop.owner);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
isInverseRelation(prop)
|
|
95
|
+
{
|
|
96
|
+
if('1:m' === prop.kind){
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return '1:1' === prop.kind && !prop.owner;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
inverseRelationOwnerJoinColumn(prop, relationDriver)
|
|
103
|
+
{
|
|
104
|
+
if(!this.isInverseRelation(prop)){
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if(!prop.mappedBy){
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if(!relationDriver.entitySchema){
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if(!relationDriver.entitySchema.meta){
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
let mappedProp = relationDriver.entitySchema.meta.properties[prop.mappedBy];
|
|
117
|
+
if(!mappedProp){
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if(!mappedProp.joinColumns){
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return mappedProp.joinColumns[0] || false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
nestedFkColumn(prop, relationDriver)
|
|
127
|
+
{
|
|
128
|
+
if(!this.isOwningRelation(prop)){
|
|
129
|
+
return this.inverseRelationOwnerJoinColumn(prop, relationDriver);
|
|
130
|
+
}
|
|
131
|
+
if(!prop.joinColumns){
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return prop.joinColumns[0] || false;
|
|
135
|
+
}
|
|
136
|
+
|
|
86
137
|
async create(params)
|
|
87
138
|
{
|
|
88
139
|
let transformed = this.transformFkToRelations(params);
|
|
@@ -207,7 +258,7 @@ class MikroOrmDriver extends BaseDriver
|
|
|
207
258
|
let aliasCounter = 0;
|
|
208
259
|
for(let relationName of relations){
|
|
209
260
|
let prop = properties[relationName];
|
|
210
|
-
if(!prop || !prop.kind || (prop
|
|
261
|
+
if(!prop || !prop.kind || (!this.isOwningRelation(prop) && !this.isInverseRelation(prop))){
|
|
211
262
|
continue;
|
|
212
263
|
}
|
|
213
264
|
let relationDriver = this.server.entityManager.get(prop.entity);
|
|
@@ -215,14 +266,12 @@ class MikroOrmDriver extends BaseDriver
|
|
|
215
266
|
continue;
|
|
216
267
|
}
|
|
217
268
|
let alias = 'rel_'+aliasCounter;
|
|
218
|
-
if(
|
|
269
|
+
if(this.isOwningRelation(prop) && prop.joinColumns && prop.joinColumns[0]){
|
|
219
270
|
queryBuilder.leftJoin(relationName, alias, 'e.'+prop.joinColumns[0]+' = '+alias+'.id');
|
|
220
271
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
queryBuilder.leftJoin(relationName, alias, 'e.id = '+alias+'.'+mappedProp.joinColumns[0]);
|
|
225
|
-
}
|
|
272
|
+
let ownerJoinColumn = this.inverseRelationOwnerJoinColumn(prop, relationDriver);
|
|
273
|
+
if(ownerJoinColumn){
|
|
274
|
+
queryBuilder.leftJoin(relationName, alias, 'e.id = '+alias+'.'+ownerJoinColumn);
|
|
226
275
|
}
|
|
227
276
|
aliasCounter++;
|
|
228
277
|
}
|
|
@@ -424,7 +473,7 @@ class MikroOrmDriver extends BaseDriver
|
|
|
424
473
|
return entity;
|
|
425
474
|
}
|
|
426
475
|
for(let key of Object.keys(entity)){
|
|
427
|
-
if(entity[key] && entity[key] instanceof Collection){
|
|
476
|
+
if(entity[key] && entity[key] instanceof Collection && entity[key].isInitialized()){
|
|
428
477
|
entity[key] = entity[key].getItems();
|
|
429
478
|
}
|
|
430
479
|
}
|
|
@@ -479,7 +528,7 @@ class MikroOrmDriver extends BaseDriver
|
|
|
479
528
|
let properties = this.entitySchema.meta.properties;
|
|
480
529
|
for(let relationName of Object.keys(properties)){
|
|
481
530
|
let prop = properties[relationName];
|
|
482
|
-
if(!prop.kind || (prop
|
|
531
|
+
if(!prop.kind || (!this.isOwningRelation(prop) && !this.isInverseRelation(prop))){
|
|
483
532
|
continue;
|
|
484
533
|
}
|
|
485
534
|
if(sc.isArray(relations) && 0 < relations.length && -1 === relations.indexOf(relationName)){
|
|
@@ -490,14 +539,19 @@ class MikroOrmDriver extends BaseDriver
|
|
|
490
539
|
Logger.warning('Entity not found for relation:', prop.entity);
|
|
491
540
|
continue;
|
|
492
541
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
542
|
+
if(!sc.hasOwn(params, relationName)){
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if(this.isOwningRelation(prop)){
|
|
496
546
|
await this.createOne(params, relationName, relationDriver, newInstance, prop);
|
|
497
547
|
continue;
|
|
498
548
|
}
|
|
499
|
-
if(
|
|
549
|
+
if(sc.isArray(params[relationName])){
|
|
500
550
|
await this.createMany(params, relationName, relationDriver, newInstance, prop);
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if('1:1' === prop.kind && sc.isObject(params[relationName])){
|
|
554
|
+
await this.createOne(params, relationName, relationDriver, newInstance, prop);
|
|
501
555
|
}
|
|
502
556
|
}
|
|
503
557
|
}
|
|
@@ -505,8 +559,9 @@ class MikroOrmDriver extends BaseDriver
|
|
|
505
559
|
async createOne(params, relationName, relationDriver, newInstance, prop)
|
|
506
560
|
{
|
|
507
561
|
let nestedData = params[relationName];
|
|
508
|
-
|
|
509
|
-
|
|
562
|
+
let fkColumn = this.nestedFkColumn(prop, relationDriver);
|
|
563
|
+
if(fkColumn){
|
|
564
|
+
nestedData[fkColumn] = newInstance.id;
|
|
510
565
|
}
|
|
511
566
|
let nestedObject = await relationDriver.create(nestedData);
|
|
512
567
|
await this.orm.em.flush();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reldens/storage",
|
|
3
3
|
"scope": "@reldens",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.117.0",
|
|
5
5
|
"description": "Reldens - Storage",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -51,14 +51,14 @@
|
|
|
51
51
|
"test:driver": "node tests/run-tests.js --driver="
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@mikro-orm/core": "7.
|
|
55
|
-
"@mikro-orm/mongodb": "7.
|
|
56
|
-
"@mikro-orm/mysql": "7.
|
|
54
|
+
"@mikro-orm/core": "7.2.0",
|
|
55
|
+
"@mikro-orm/mongodb": "7.2.0",
|
|
56
|
+
"@mikro-orm/mysql": "7.2.0",
|
|
57
57
|
"@reldens/server-utils": "^0.57.0",
|
|
58
58
|
"@reldens/utils": "^0.58.0",
|
|
59
59
|
"knex": "3.3.0",
|
|
60
60
|
"mysql": "2.18.1",
|
|
61
|
-
"mysql2": "3.24.
|
|
61
|
+
"mysql2": "3.24.4",
|
|
62
62
|
"objection": "3.1.5"
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - TestProductDetailsEntity
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { EntityProperties } = require('../../index');
|
|
8
|
+
const { sc } = require('@reldens/utils');
|
|
9
|
+
|
|
10
|
+
class TestProductDetailsEntity extends EntityProperties
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
static propertiesConfig(extraProps)
|
|
14
|
+
{
|
|
15
|
+
let properties = {
|
|
16
|
+
id: {
|
|
17
|
+
isId: true,
|
|
18
|
+
type: 'number',
|
|
19
|
+
isRequired: true,
|
|
20
|
+
dbType: 'int'
|
|
21
|
+
},
|
|
22
|
+
product_id: {
|
|
23
|
+
type: 'reference',
|
|
24
|
+
reference: 'test_products',
|
|
25
|
+
alias: 'related_test_products',
|
|
26
|
+
onDelete: 'cascade',
|
|
27
|
+
isRequired: true,
|
|
28
|
+
isUnique: true,
|
|
29
|
+
dbType: 'int'
|
|
30
|
+
},
|
|
31
|
+
weight: {
|
|
32
|
+
type: 'number',
|
|
33
|
+
dbType: 'decimal'
|
|
34
|
+
},
|
|
35
|
+
dimensions: {
|
|
36
|
+
dbType: 'varchar'
|
|
37
|
+
},
|
|
38
|
+
created_at: {
|
|
39
|
+
type: 'datetime',
|
|
40
|
+
dbType: 'timestamp'
|
|
41
|
+
},
|
|
42
|
+
updated_at: {
|
|
43
|
+
type: 'datetime',
|
|
44
|
+
dbType: 'timestamp'
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
let propertiesKeys = Object.keys(properties);
|
|
48
|
+
let showProperties = propertiesKeys;
|
|
49
|
+
let editProperties = sc.removeFromArray([...propertiesKeys], ['id', 'created_at', 'updated_at']);
|
|
50
|
+
let listProperties = propertiesKeys;
|
|
51
|
+
return {
|
|
52
|
+
showProperties,
|
|
53
|
+
editProperties,
|
|
54
|
+
listProperties,
|
|
55
|
+
filterProperties: listProperties,
|
|
56
|
+
properties,
|
|
57
|
+
...extraProps
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports.TestProductDetailsEntity = TestProductDetailsEntity;
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { TestCategoriesEntity } = require('./entities/test-categories-entity');
|
|
8
|
-
const {
|
|
7
|
+
const { TestCategoriesEntity } = require('./entities/test-categories-entity');
|
|
8
|
+
const { TestProductDetailsEntity } = require('./entities/test-product-details-entity');
|
|
9
|
+
const { TestProductsEntity } = require('./entities/test-products-entity');
|
|
9
10
|
const { TestReviewsEntity } = require('./entities/test-reviews-entity');
|
|
10
11
|
|
|
11
12
|
let entitiesConfig = {
|
|
12
|
-
testCategories: TestCategoriesEntity.propertiesConfig(),
|
|
13
|
-
|
|
13
|
+
testCategories: TestCategoriesEntity.propertiesConfig(),
|
|
14
|
+
testProductDetails: TestProductDetailsEntity.propertiesConfig(),
|
|
15
|
+
testProducts: TestProductsEntity.propertiesConfig(),
|
|
14
16
|
testReviews: TestReviewsEntity.propertiesConfig()
|
|
15
17
|
};
|
|
16
18
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Reldens - Entities Translations
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
module.exports.entitiesTranslations = {
|
|
8
|
-
labels: {
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - Entities Translations
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
module.exports.entitiesTranslations = {
|
|
8
|
+
labels: {
|
|
9
9
|
'test_categories': 'Test Categories',
|
|
10
|
+
'test_product_details': 'Test Product Details',
|
|
10
11
|
'test_products': 'Test Products',
|
|
11
|
-
'test_reviews': 'Test Reviews'
|
|
12
|
-
},
|
|
13
|
-
fields: {
|
|
12
|
+
'test_reviews': 'Test Reviews'
|
|
13
|
+
},
|
|
14
|
+
fields: {
|
|
14
15
|
'test_categories': {
|
|
15
16
|
'id': 'ID',
|
|
16
17
|
'name': 'Name',
|
|
@@ -21,6 +22,14 @@ module.exports.entitiesTranslations = {
|
|
|
21
22
|
'created_at': 'Created At',
|
|
22
23
|
'updated_at': 'Updated At'
|
|
23
24
|
},
|
|
25
|
+
'test_product_details': {
|
|
26
|
+
'id': 'ID',
|
|
27
|
+
'product_id': 'Product ID',
|
|
28
|
+
'weight': 'Weight',
|
|
29
|
+
'dimensions': 'Dimensions',
|
|
30
|
+
'created_at': 'Created At',
|
|
31
|
+
'updated_at': 'Updated At'
|
|
32
|
+
},
|
|
24
33
|
'test_products': {
|
|
25
34
|
'id': 'ID',
|
|
26
35
|
'category_id': 'Category ID',
|
|
@@ -48,6 +57,6 @@ module.exports.entitiesTranslations = {
|
|
|
48
57
|
'helpful_count': 'Helpful Count',
|
|
49
58
|
'created_at': 'Created At',
|
|
50
59
|
'updated_at': 'Updated At'
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/registered-models-mikro-orm.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const testCategoriesModel = require('./test-categories-model');
|
|
8
|
+
const testProductDetailsModel = require('./test-product-details-model');
|
|
8
9
|
const testProductsModel = require('./test-products-model');
|
|
9
10
|
const testReviewsModel = require('./test-reviews-model');
|
|
10
11
|
const { entitiesConfig } = require('../../entities-config');
|
|
@@ -12,6 +13,7 @@ const { entitiesTranslations } = require('../../entities-translations');
|
|
|
12
13
|
|
|
13
14
|
let rawRegisteredEntities = {
|
|
14
15
|
testCategories: testCategoriesModel,
|
|
16
|
+
testProductDetails: testProductDetailsModel,
|
|
15
17
|
testProducts: testProductsModel,
|
|
16
18
|
testReviews: testReviewsModel
|
|
17
19
|
};
|
package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - TestProductDetailsModel
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { MikroOrmCore } = require('../../../index');
|
|
8
|
+
const { EntitySchema } = MikroOrmCore;
|
|
9
|
+
|
|
10
|
+
class TestProductDetailsModel
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor(id, product_id, weight, dimensions, created_at, updated_at)
|
|
14
|
+
{
|
|
15
|
+
this.id = id;
|
|
16
|
+
this.product_id = product_id;
|
|
17
|
+
this.weight = weight;
|
|
18
|
+
this.dimensions = dimensions;
|
|
19
|
+
this.created_at = created_at;
|
|
20
|
+
this.updated_at = updated_at;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static createByProps(props)
|
|
24
|
+
{
|
|
25
|
+
const {id, product_id, weight, dimensions, created_at, updated_at} = props;
|
|
26
|
+
return new this(id, product_id, weight, dimensions, created_at, updated_at);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const schema = new EntitySchema({
|
|
32
|
+
class: TestProductDetailsModel,
|
|
33
|
+
tableName: 'test_product_details',
|
|
34
|
+
properties: {
|
|
35
|
+
id: { type: 'number', primary: true },
|
|
36
|
+
product_id: { type: 'number', persist: false },
|
|
37
|
+
weight: { type: 'number', nullable: true },
|
|
38
|
+
dimensions: { type: 'string', nullable: true },
|
|
39
|
+
created_at: { type: 'Date', nullable: true },
|
|
40
|
+
updated_at: { type: 'Date', nullable: true },
|
|
41
|
+
related_test_products: {
|
|
42
|
+
kind: '1:1',
|
|
43
|
+
entity: () => require('./test-products-model').TestProductsModel,
|
|
44
|
+
joinColumns: ['product_id']
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
schema._fkMappings = {
|
|
49
|
+
"product_id": {
|
|
50
|
+
"relationKey": "related_test_products",
|
|
51
|
+
"entityName": "TestProductsModel",
|
|
52
|
+
"referencedColumn": "id",
|
|
53
|
+
"nullable": false
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
module.exports = {
|
|
57
|
+
TestProductDetailsModel,
|
|
58
|
+
entity: TestProductDetailsModel,
|
|
59
|
+
schema: schema
|
|
60
|
+
};
|
|
@@ -57,6 +57,11 @@ const schema = new EntitySchema({
|
|
|
57
57
|
entity: () => require('./test-categories-model').TestCategoriesModel,
|
|
58
58
|
joinColumns: ['category_id']
|
|
59
59
|
},
|
|
60
|
+
related_test_product_details: {
|
|
61
|
+
kind: '1:1',
|
|
62
|
+
entity: () => require('./test-product-details-model').TestProductDetailsModel,
|
|
63
|
+
mappedBy: 'related_test_products'
|
|
64
|
+
},
|
|
60
65
|
related_test_reviews: {
|
|
61
66
|
kind: '1:m',
|
|
62
67
|
entity: () => require('./test-reviews-model').TestReviewsModel,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { TestCategoriesModel } = require('./test-categories-model');
|
|
8
|
+
const { TestProductDetailsModel } = require('./test-product-details-model');
|
|
8
9
|
const { TestProductsModel } = require('./test-products-model');
|
|
9
10
|
const { TestReviewsModel } = require('./test-reviews-model');
|
|
10
11
|
const { entitiesConfig } = require('../../entities-config');
|
|
@@ -12,6 +13,7 @@ const { entitiesTranslations } = require('../../entities-translations');
|
|
|
12
13
|
|
|
13
14
|
let rawRegisteredEntities = {
|
|
14
15
|
testCategories: TestCategoriesModel,
|
|
16
|
+
testProductDetails: TestProductDetailsModel,
|
|
15
17
|
testProducts: TestProductsModel,
|
|
16
18
|
testReviews: TestReviewsModel
|
|
17
19
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - TestProductDetailsModel
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ObjectionJsRawModel } = require('../../../index');
|
|
8
|
+
|
|
9
|
+
class TestProductDetailsModel extends ObjectionJsRawModel
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
static get tableName()
|
|
13
|
+
{
|
|
14
|
+
return 'test_product_details';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static get relationMappings()
|
|
18
|
+
{
|
|
19
|
+
const { TestProductsModel } = require('./test-products-model');
|
|
20
|
+
return {
|
|
21
|
+
related_test_products: {
|
|
22
|
+
relation: this.BelongsToOneRelation,
|
|
23
|
+
modelClass: TestProductsModel,
|
|
24
|
+
join: {
|
|
25
|
+
from: this.tableName+'.product_id',
|
|
26
|
+
to: TestProductsModel.tableName+'.id'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports.TestProductDetailsModel = TestProductDetailsModel;
|
package/tests/fixtures/expected-entities-objection-js/models/objection-js/test-products-model.js
CHANGED
|
@@ -17,6 +17,7 @@ class TestProductsModel extends ObjectionJsRawModel
|
|
|
17
17
|
static get relationMappings()
|
|
18
18
|
{
|
|
19
19
|
const { TestCategoriesModel } = require('./test-categories-model');
|
|
20
|
+
const { TestProductDetailsModel } = require('./test-product-details-model');
|
|
20
21
|
const { TestReviewsModel } = require('./test-reviews-model');
|
|
21
22
|
return {
|
|
22
23
|
related_test_categories: {
|
|
@@ -27,6 +28,14 @@ class TestProductsModel extends ObjectionJsRawModel
|
|
|
27
28
|
to: TestCategoriesModel.tableName+'.id'
|
|
28
29
|
}
|
|
29
30
|
},
|
|
31
|
+
related_test_product_details: {
|
|
32
|
+
relation: this.HasOneRelation,
|
|
33
|
+
modelClass: TestProductDetailsModel,
|
|
34
|
+
join: {
|
|
35
|
+
from: this.tableName+'.id',
|
|
36
|
+
to: TestProductDetailsModel.tableName+'.product_id'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
30
39
|
related_test_reviews: {
|
|
31
40
|
relation: this.HasManyRelation,
|
|
32
41
|
modelClass: TestReviewsModel,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { TestCategoriesModel } = require('./test-categories-model');
|
|
8
|
+
const { TestProductDetailsModel } = require('./test-product-details-model');
|
|
8
9
|
const { TestProductsModel } = require('./test-products-model');
|
|
9
10
|
const { TestReviewsModel } = require('./test-reviews-model');
|
|
10
11
|
const { entitiesConfig } = require('../../entities-config');
|
|
@@ -12,6 +13,7 @@ const { entitiesTranslations } = require('../../entities-translations');
|
|
|
12
13
|
|
|
13
14
|
let rawRegisteredEntities = {
|
|
14
15
|
testCategories: TestCategoriesModel,
|
|
16
|
+
testProductDetails: TestProductDetailsModel,
|
|
15
17
|
testProducts: TestProductsModel,
|
|
16
18
|
testReviews: TestReviewsModel
|
|
17
19
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - TestProductDetailsModel
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class TestProductDetailsModel
|
|
8
|
+
{
|
|
9
|
+
|
|
10
|
+
constructor(id, product_id, weight, dimensions, created_at, updated_at)
|
|
11
|
+
{
|
|
12
|
+
this.id = id;
|
|
13
|
+
this.product_id = product_id;
|
|
14
|
+
this.weight = weight;
|
|
15
|
+
this.dimensions = dimensions;
|
|
16
|
+
this.created_at = created_at;
|
|
17
|
+
this.updated_at = updated_at;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static get tableName()
|
|
21
|
+
{
|
|
22
|
+
return 'test_product_details';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
static get relationTypes()
|
|
27
|
+
{
|
|
28
|
+
return {
|
|
29
|
+
test_products: 'one'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static get relationMappings()
|
|
34
|
+
{
|
|
35
|
+
return {
|
|
36
|
+
'related_test_products': 'test_products'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports.TestProductDetailsModel = TestProductDetailsModel;
|
|
@@ -34,6 +34,7 @@ class TestProductsModel
|
|
|
34
34
|
{
|
|
35
35
|
return {
|
|
36
36
|
test_categories: 'one',
|
|
37
|
+
test_product_details: 'one',
|
|
37
38
|
test_reviews: 'many'
|
|
38
39
|
};
|
|
39
40
|
}
|
|
@@ -42,6 +43,7 @@ class TestProductsModel
|
|
|
42
43
|
{
|
|
43
44
|
return {
|
|
44
45
|
'related_test_categories': 'test_categories',
|
|
46
|
+
'related_test_product_details': 'test_product_details',
|
|
45
47
|
'related_test_reviews': 'test_reviews'
|
|
46
48
|
};
|
|
47
49
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - Test Product Details Fixtures
|
|
4
|
+
* Universal fixtures for all drivers (no driver-specific nesting)
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
module.exports.ProductDetailsFixtures = {
|
|
9
|
+
product_details_relations_1: {
|
|
10
|
+
id: 4600,
|
|
11
|
+
product_id: 2600,
|
|
12
|
+
weight: 1.25,
|
|
13
|
+
dimensions: '10x20x30'
|
|
14
|
+
},
|
|
15
|
+
product_details_create_nested: {
|
|
16
|
+
weight: 2.5,
|
|
17
|
+
dimensions: '5x5x5'
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
DROP TABLE IF EXISTS `test_reviews`;
|
|
2
|
+
DROP TABLE IF EXISTS `test_product_details`;
|
|
2
3
|
DROP TABLE IF EXISTS `test_products`;
|
|
3
4
|
DROP TABLE IF EXISTS `test_categories`;
|
|
4
5
|
|
|
@@ -39,6 +40,18 @@ CREATE TABLE `test_products` (
|
|
|
39
40
|
CONSTRAINT `fk_products_category` FOREIGN KEY (`category_id`) REFERENCES `test_categories` (`id`) ON DELETE CASCADE
|
|
40
41
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
41
42
|
|
|
43
|
+
CREATE TABLE `test_product_details` (
|
|
44
|
+
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
45
|
+
`product_id` INT UNSIGNED NOT NULL,
|
|
46
|
+
`weight` DECIMAL(10,2) NULL,
|
|
47
|
+
`dimensions` VARCHAR(100) NULL,
|
|
48
|
+
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
49
|
+
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
50
|
+
PRIMARY KEY (`id`),
|
|
51
|
+
UNIQUE KEY `product_id` (`product_id`),
|
|
52
|
+
CONSTRAINT `fk_product_details_product` FOREIGN KEY (`product_id`) REFERENCES `test_products` (`id`) ON DELETE CASCADE
|
|
53
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
54
|
+
|
|
42
55
|
CREATE TABLE `test_reviews` (
|
|
43
56
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
44
57
|
`product_id` INT UNSIGNED NOT NULL,
|
|
@@ -10,6 +10,7 @@ const { TestHelpers } = require('../utils/test-helpers');
|
|
|
10
10
|
const { CategoriesFixtures } = require('../fixtures/categories-fixtures');
|
|
11
11
|
const { ProductsFixtures } = require('../fixtures/products-fixtures');
|
|
12
12
|
const { ReviewsFixtures } = require('../fixtures/reviews-fixtures');
|
|
13
|
+
const { ProductDetailsFixtures } = require('../fixtures/product-details-fixtures');
|
|
13
14
|
|
|
14
15
|
class RelationsTest
|
|
15
16
|
{
|
|
@@ -19,6 +20,7 @@ class RelationsTest
|
|
|
19
20
|
this.dataServer = dataServer;
|
|
20
21
|
this.categoriesRepo = repos.testCategories;
|
|
21
22
|
this.productsRepo = repos.testProducts;
|
|
23
|
+
this.productDetailsRepo = repos.testProductDetails;
|
|
22
24
|
this.driverName = driverName;
|
|
23
25
|
this.runner = new TestRunner();
|
|
24
26
|
}
|
|
@@ -36,9 +38,71 @@ class RelationsTest
|
|
|
36
38
|
await this.testCreateWithRelations();
|
|
37
39
|
await this.testNestedRelations();
|
|
38
40
|
await this.testRelationStringParsing();
|
|
41
|
+
await this.testOneToOneRelations();
|
|
39
42
|
return this.runner.getResults();
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
async testOneToOneRelations()
|
|
46
|
+
{
|
|
47
|
+
this.runner.group('One To One Relations');
|
|
48
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
49
|
+
await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_categories', [
|
|
50
|
+
CategoriesFixtures.category_relations_1
|
|
51
|
+
]);
|
|
52
|
+
await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_products', [
|
|
53
|
+
ProductsFixtures.product_relations_1,
|
|
54
|
+
{...ProductsFixtures.product_relations_2, category_id: 1600}
|
|
55
|
+
]);
|
|
56
|
+
await TestHelpers.insertFixturesViaRawSQL(this.dataServer, 'test_product_details', [
|
|
57
|
+
ProductDetailsFixtures.product_details_relations_1
|
|
58
|
+
]);
|
|
59
|
+
await this.runner.test('should load the one to one relation from the referenced side as a single object', async () => {
|
|
60
|
+
let results = await this.productsRepo.loadWithRelations({id: 2600}, ['related_test_product_details']);
|
|
61
|
+
assert.strictEqual(results.length, 1);
|
|
62
|
+
let details = results[0].related_test_product_details;
|
|
63
|
+
assert.ok(details);
|
|
64
|
+
assert.ok(!Array.isArray(details));
|
|
65
|
+
assert.strictEqual(details.id, 4600);
|
|
66
|
+
});
|
|
67
|
+
await this.runner.test('should load the one to one relation from the owning side as a single object', async () => {
|
|
68
|
+
let results = await this.productDetailsRepo.loadWithRelations({id: 4600}, ['related_test_products']);
|
|
69
|
+
assert.strictEqual(results.length, 1);
|
|
70
|
+
let product = results[0].related_test_products;
|
|
71
|
+
assert.ok(product);
|
|
72
|
+
assert.ok(!Array.isArray(product));
|
|
73
|
+
assert.strictEqual(product.id, 2600);
|
|
74
|
+
});
|
|
75
|
+
await this.runner.test('should return no related record on the one to one relation when none exists', async () => {
|
|
76
|
+
let result = await this.productsRepo.loadByIdWithRelations(2601, ['related_test_product_details']);
|
|
77
|
+
assert.ok(result);
|
|
78
|
+
assert.ok(!result.related_test_product_details);
|
|
79
|
+
});
|
|
80
|
+
await this.runner.test('should count records joining the one to one relation from the referenced side', async () => {
|
|
81
|
+
let count = await this.productsRepo.countWithRelations({}, ['related_test_product_details']);
|
|
82
|
+
assert.strictEqual(count, 2);
|
|
83
|
+
});
|
|
84
|
+
await this.runner.test('should count records joining the one to one relation from the owning side', async () => {
|
|
85
|
+
let count = await this.productDetailsRepo.countWithRelations({}, ['related_test_products']);
|
|
86
|
+
assert.strictEqual(count, 1);
|
|
87
|
+
});
|
|
88
|
+
await this.runner.test('should create a record with a nested one to one relation', async () => {
|
|
89
|
+
let productWithDetails = {
|
|
90
|
+
...ProductsFixtures.product_create_nested,
|
|
91
|
+
category_id: 1600,
|
|
92
|
+
related_test_product_details: {...ProductDetailsFixtures.product_details_create_nested}
|
|
93
|
+
};
|
|
94
|
+
let created = await this.productsRepo.createWithRelations(
|
|
95
|
+
productWithDetails,
|
|
96
|
+
['related_test_product_details']
|
|
97
|
+
);
|
|
98
|
+
assert.ok(created);
|
|
99
|
+
assert.ok(created.id);
|
|
100
|
+
let details = await this.productDetailsRepo.loadBy('product_id', created.id);
|
|
101
|
+
assert.strictEqual(details.length, 1);
|
|
102
|
+
assert.strictEqual(details[0].dimensions, ProductDetailsFixtures.product_details_create_nested.dimensions);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
42
106
|
async testLoadWithRelations()
|
|
43
107
|
{
|
|
44
108
|
this.runner.group('loadWithRelations');
|
package/tests/run-tests.js
CHANGED
|
@@ -16,6 +16,7 @@ const EntityManagerTest = require('./unit/test-entity-manager');
|
|
|
16
16
|
const TypeMapperTest = require('./unit/test-type-mapper');
|
|
17
17
|
const DriversUnitTest = require('./unit/test-drivers');
|
|
18
18
|
const EntitiesGenerationTest = require('./unit/test-entities-generation');
|
|
19
|
+
const ModelsGenerationTest = require('./unit/test-models-generation');
|
|
19
20
|
|
|
20
21
|
if(!process.env.RELDENS_TEST_DB_HOST){
|
|
21
22
|
let envPath = FileHandler.joinPaths(__dirname, '.env.test');
|
|
@@ -193,6 +194,11 @@ class RunTests
|
|
|
193
194
|
this.allCounts.total += entitiesGenerationResult.total;
|
|
194
195
|
this.allCounts.passed += entitiesGenerationResult.passed;
|
|
195
196
|
this.allCounts.failed += entitiesGenerationResult.failed;
|
|
197
|
+
let modelsGenerationTest = new ModelsGenerationTest();
|
|
198
|
+
let modelsGenerationResult = await modelsGenerationTest.run();
|
|
199
|
+
this.allCounts.total += modelsGenerationResult.total;
|
|
200
|
+
this.allCounts.passed += modelsGenerationResult.passed;
|
|
201
|
+
this.allCounts.failed += modelsGenerationResult.failed;
|
|
196
202
|
}
|
|
197
203
|
|
|
198
204
|
async runPreFlightChecks(config)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - ModelsGeneration Test
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { TestRunner, assert } = require('../utils/test-runner');
|
|
8
|
+
const { ModelsGeneration } = require('../../lib/generators/models-generation');
|
|
9
|
+
|
|
10
|
+
class ModelsGenerationTest
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor()
|
|
14
|
+
{
|
|
15
|
+
this.runner = new TestRunner();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
createColumn(props)
|
|
19
|
+
{
|
|
20
|
+
return Object.assign(
|
|
21
|
+
{
|
|
22
|
+
name: 'test_column',
|
|
23
|
+
type: 'int',
|
|
24
|
+
columnType: 'int(10) unsigned',
|
|
25
|
+
length: null,
|
|
26
|
+
nullable: false,
|
|
27
|
+
key: '',
|
|
28
|
+
extra: '',
|
|
29
|
+
default: null
|
|
30
|
+
},
|
|
31
|
+
props
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
createForeignKeyColumn(name, key)
|
|
36
|
+
{
|
|
37
|
+
return this.createColumn({
|
|
38
|
+
name,
|
|
39
|
+
key,
|
|
40
|
+
referencedTable: 'test_products',
|
|
41
|
+
referencedColumn: 'id',
|
|
42
|
+
referencedDeleteRule: 'CASCADE'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
createTables()
|
|
47
|
+
{
|
|
48
|
+
return {
|
|
49
|
+
test_products: {
|
|
50
|
+
name: 'test_products',
|
|
51
|
+
columns: {
|
|
52
|
+
id: this.createColumn({name: 'id', key: 'PRI', extra: 'auto_increment'}),
|
|
53
|
+
name: this.createColumn({name: 'name', type: 'varchar', columnType: 'varchar(200)', length: '200'})
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
test_product_details: {
|
|
57
|
+
name: 'test_product_details',
|
|
58
|
+
columns: {
|
|
59
|
+
id: this.createColumn({name: 'id', key: 'PRI', extra: 'auto_increment'}),
|
|
60
|
+
product_id: this.createForeignKeyColumn('product_id', 'UNI')
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
test_reviews: {
|
|
64
|
+
name: 'test_reviews',
|
|
65
|
+
columns: {
|
|
66
|
+
id: this.createColumn({name: 'id', key: 'PRI', extra: 'auto_increment'}),
|
|
67
|
+
product_id: this.createForeignKeyColumn('product_id', 'MUL')
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
createGeneration()
|
|
74
|
+
{
|
|
75
|
+
let generation = new ModelsGeneration({});
|
|
76
|
+
generation.setAllTablesData(this.createTables());
|
|
77
|
+
return generation;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
mikroOrmDefinition(generation, tableName)
|
|
81
|
+
{
|
|
82
|
+
let tableData = generation.allTablesData[tableName];
|
|
83
|
+
return generation.getEntityPropertiesDefinition(tableData.columns, 'mikro-orm', tableName, tableData);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async run()
|
|
87
|
+
{
|
|
88
|
+
this.runner.suite('ModelsGeneration');
|
|
89
|
+
await this.testDetermineMikroOrmForwardKind();
|
|
90
|
+
await this.testMikroOrmOneToOneDefinitions();
|
|
91
|
+
await this.testObjectionJsRelationTypes();
|
|
92
|
+
return this.runner.getResults();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async testDetermineMikroOrmForwardKind()
|
|
96
|
+
{
|
|
97
|
+
this.runner.group('determineMikroOrmForwardKind');
|
|
98
|
+
let generation = this.createGeneration();
|
|
99
|
+
await this.runner.test('should return 1:1 for a unique foreign key column', async () => {
|
|
100
|
+
let kind = generation.determineMikroOrmForwardKind(this.createColumn({key: 'UNI'}));
|
|
101
|
+
assert.strictEqual(kind, '1:1');
|
|
102
|
+
});
|
|
103
|
+
await this.runner.test('should return 1:1 for a primary foreign key column', async () => {
|
|
104
|
+
let kind = generation.determineMikroOrmForwardKind(this.createColumn({key: 'PRI'}));
|
|
105
|
+
assert.strictEqual(kind, '1:1');
|
|
106
|
+
});
|
|
107
|
+
await this.runner.test('should return m:1 for an indexed foreign key column', async () => {
|
|
108
|
+
let kind = generation.determineMikroOrmForwardKind(this.createColumn({key: 'MUL'}));
|
|
109
|
+
assert.strictEqual(kind, 'm:1');
|
|
110
|
+
});
|
|
111
|
+
await this.runner.test('should return m:1 for a non indexed foreign key column', async () => {
|
|
112
|
+
let kind = generation.determineMikroOrmForwardKind(this.createColumn({key: ''}));
|
|
113
|
+
assert.strictEqual(kind, 'm:1');
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async testMikroOrmOneToOneDefinitions()
|
|
118
|
+
{
|
|
119
|
+
this.runner.group('getEntityPropertiesDefinition - mikro-orm one to one');
|
|
120
|
+
let generation = this.createGeneration();
|
|
121
|
+
await this.runner.test('should emit a 1:1 owning side with joinColumns for a unique foreign key', async () => {
|
|
122
|
+
let definition = this.mikroOrmDefinition(generation, 'test_product_details');
|
|
123
|
+
assert.ok(definition.includes('related_test_products: {\n kind: \'1:1\','));
|
|
124
|
+
assert.ok(definition.includes('joinColumns: [\'product_id\']'));
|
|
125
|
+
assert.ok(!definition.includes('mappedBy'));
|
|
126
|
+
});
|
|
127
|
+
await this.runner.test('should emit a 1:1 inverse side with mappedBy for a unique foreign key', async () => {
|
|
128
|
+
let definition = this.mikroOrmDefinition(generation, 'test_products');
|
|
129
|
+
assert.ok(definition.includes('related_test_product_details: {\n kind: \'1:1\','));
|
|
130
|
+
assert.ok(definition.includes('mappedBy: \'related_test_products\''));
|
|
131
|
+
});
|
|
132
|
+
await this.runner.test('should emit a 1:m inverse side for a non unique foreign key', async () => {
|
|
133
|
+
let definition = this.mikroOrmDefinition(generation, 'test_products');
|
|
134
|
+
assert.ok(definition.includes('related_test_reviews: {\n kind: \'1:m\','));
|
|
135
|
+
});
|
|
136
|
+
await this.runner.test('should emit a m:1 owning side for a non unique foreign key', async () => {
|
|
137
|
+
let definition = this.mikroOrmDefinition(generation, 'test_reviews');
|
|
138
|
+
assert.ok(definition.includes('related_test_products: {\n kind: \'m:1\','));
|
|
139
|
+
assert.ok(definition.includes('joinColumns: [\'product_id\']'));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async testObjectionJsRelationTypes()
|
|
144
|
+
{
|
|
145
|
+
this.runner.group('ObjectionJS relation types for unique foreign keys');
|
|
146
|
+
let generation = this.createGeneration();
|
|
147
|
+
let tables = generation.allTablesData;
|
|
148
|
+
await this.runner.test('should keep BelongsToOneRelation on the owning side', async () => {
|
|
149
|
+
let relations = generation.detectObjectionJsRelations('test_product_details', tables.test_product_details);
|
|
150
|
+
assert.strictEqual(relations.related_test_products.relationType, 'BelongsToOneRelation');
|
|
151
|
+
});
|
|
152
|
+
await this.runner.test('should use HasOneRelation on the referenced side of a unique foreign key', async () => {
|
|
153
|
+
let reverseRelations = generation.detectReverseObjectionJsRelations('test_products');
|
|
154
|
+
assert.strictEqual(reverseRelations.related_test_product_details.relationType, 'HasOneRelation');
|
|
155
|
+
});
|
|
156
|
+
await this.runner.test('should use HasManyRelation on the referenced side of a non unique foreign key', async () => {
|
|
157
|
+
let reverseRelations = generation.detectReverseObjectionJsRelations('test_products');
|
|
158
|
+
assert.strictEqual(reverseRelations.related_test_reviews.relationType, 'HasManyRelation');
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = ModelsGenerationTest;
|
|
@@ -22,7 +22,7 @@ class DriverRegistry
|
|
|
22
22
|
instanceId: Math.random()
|
|
23
23
|
};
|
|
24
24
|
this.schemaPath = FileHandler.joinPaths(__dirname, '..', 'fixtures', 'sql', 'test-schema.sql');
|
|
25
|
-
this.repoNames = ['testCategories', 'testProducts', 'testReviews'];
|
|
25
|
+
this.repoNames = ['testCategories', 'testProductDetails', 'testProducts', 'testReviews'];
|
|
26
26
|
this.driverNames = TestHelpers.activeDriverNames();
|
|
27
27
|
this.skipGeneration = false;
|
|
28
28
|
}
|
|
@@ -156,6 +156,7 @@ class TestHelpers
|
|
|
156
156
|
try {
|
|
157
157
|
await dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=0;');
|
|
158
158
|
await dataServer.rawQuery('DELETE FROM test_reviews;');
|
|
159
|
+
await dataServer.rawQuery('DELETE FROM test_product_details;');
|
|
159
160
|
await dataServer.rawQuery('DELETE FROM test_products;');
|
|
160
161
|
await dataServer.rawQuery('DELETE FROM test_categories;');
|
|
161
162
|
await dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=1;');
|
|
@@ -210,6 +211,7 @@ class TestHelpers
|
|
|
210
211
|
try {
|
|
211
212
|
await dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=0;');
|
|
212
213
|
await dataServer.rawQuery('DROP TABLE IF EXISTS test_reviews;');
|
|
214
|
+
await dataServer.rawQuery('DROP TABLE IF EXISTS test_product_details;');
|
|
213
215
|
await dataServer.rawQuery('DROP TABLE IF EXISTS test_products;');
|
|
214
216
|
await dataServer.rawQuery('DROP TABLE IF EXISTS test_categories;');
|
|
215
217
|
await dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=1;');
|
|
@@ -292,9 +294,9 @@ class TestHelpers
|
|
|
292
294
|
static verifyAllPackages()
|
|
293
295
|
{
|
|
294
296
|
let required = [
|
|
295
|
-
{name: '@mikro-orm/core', version: '7.
|
|
296
|
-
{name: '@mikro-orm/mongodb', version: '7.
|
|
297
|
-
{name: '@mikro-orm/mysql', version: '7.
|
|
297
|
+
{name: '@mikro-orm/core', version: '7.2.0'},
|
|
298
|
+
{name: '@mikro-orm/mongodb', version: '7.2.0'},
|
|
299
|
+
{name: '@mikro-orm/mysql', version: '7.2.0'},
|
|
298
300
|
{name: 'knex', version: '3.3.0'},
|
|
299
301
|
{name: 'mysql', version: '2.18.1'},
|
|
300
302
|
{name: 'mysql2', version: '3.24.3'},
|
|
@@ -719,9 +721,7 @@ class TestHelpers
|
|
|
719
721
|
for(let filename of expectedFiles){
|
|
720
722
|
let expectedContent = FileHandler.readFile(FileHandler.joinPaths(expectedPath, filename));
|
|
721
723
|
let generatedContent = FileHandler.readFile(FileHandler.joinPaths(generatedPath, filename));
|
|
722
|
-
|
|
723
|
-
let normalizedGenerated = generatedContent.replace(/\r\n/g, '\n');
|
|
724
|
-
if(normalizedExpected !== normalizedGenerated){
|
|
724
|
+
if(this.normalizeGeneratedContent(expectedContent) !== this.normalizeGeneratedContent(generatedContent)){
|
|
725
725
|
Logger.warning('File content mismatch: '+filename);
|
|
726
726
|
Logger.warning('Expected: '+FileHandler.joinPaths(expectedPath, filename));
|
|
727
727
|
Logger.warning('Generated: '+FileHandler.joinPaths(generatedPath, filename));
|
|
@@ -735,9 +735,7 @@ class TestHelpers
|
|
|
735
735
|
if(!isExpectedDir && !isGeneratedDir){
|
|
736
736
|
let expectedContent = FileHandler.readFile(expectedPath);
|
|
737
737
|
let generatedContent = FileHandler.readFile(generatedPath);
|
|
738
|
-
|
|
739
|
-
let normalizedGenerated = generatedContent.replace(/\r\n/g, '\n');
|
|
740
|
-
if(normalizedExpected !== normalizedGenerated){
|
|
738
|
+
if(this.normalizeGeneratedContent(expectedContent) !== this.normalizeGeneratedContent(generatedContent)){
|
|
741
739
|
Logger.warning('File content mismatch: '+relativePath);
|
|
742
740
|
}
|
|
743
741
|
Logger.info('File '+relativePath+' matches expected output');
|
|
@@ -746,6 +744,11 @@ class TestHelpers
|
|
|
746
744
|
throw new Error('Path type mismatch for: '+relativePath);
|
|
747
745
|
}
|
|
748
746
|
|
|
747
|
+
static normalizeGeneratedContent(content)
|
|
748
|
+
{
|
|
749
|
+
return content.replace(/\r\n/g, '\n').replace(/[ \t]+\n/g, '\n');
|
|
750
|
+
}
|
|
751
|
+
|
|
749
752
|
static async loadGeneratedEntities(dataServer, driverName)
|
|
750
753
|
{
|
|
751
754
|
let modelsPath = FileHandler.joinPaths(
|