@reldens/storage 0.116.0 → 0.118.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/.claude/test-architecture.md +27 -17
- package/CLAUDE.md +67 -11
- package/README.md +204 -22
- package/bin/reldens-storage.js +43 -10
- package/index.js +53 -12
- package/lib/drizzle/drizzle-data-server.js +123 -0
- package/lib/drizzle/drizzle-driver.js +228 -0
- package/lib/drizzle/drizzle-models-generation.js +49 -0
- package/lib/drizzle/drizzle-modules-loader.js +32 -0
- package/lib/drizzle/drizzle-modules-validator.js +74 -0
- package/lib/entities-generator.js +36 -7
- package/lib/entity-templates/drizzle-model.template +28 -0
- package/lib/entity-templates/query-builder-model.template +17 -0
- package/lib/generators/base-generator.js +13 -0
- package/lib/generators/entities-generation.js +0 -13
- package/lib/generators/models-generation.js +179 -693
- package/lib/generators/relations-detection.js +171 -0
- package/lib/knex/knex-data-server.js +128 -0
- package/lib/knex/knex-driver.js +157 -0
- package/lib/knex/knex-modules-loader.js +28 -0
- package/lib/knex/knex-modules-validator.js +45 -0
- package/lib/kysely/kysely-data-server.js +128 -0
- package/lib/kysely/kysely-driver.js +176 -0
- package/lib/kysely/kysely-modules-loader.js +28 -0
- package/lib/kysely/kysely-modules-validator.js +53 -0
- package/lib/mikro-orm/mikro-orm-data-server.js +48 -29
- package/lib/mikro-orm/mikro-orm-driver.js +385 -121
- package/lib/mikro-orm/mikro-orm-models-generation.js +178 -0
- package/lib/mikro-orm/mikro-orm-modules-loader.js +50 -0
- package/lib/mikro-orm/mikro-orm-modules-validator.js +46 -0
- package/lib/mysql2-connection-config.js +38 -0
- package/lib/objection-js/objection-js-data-server.js +71 -125
- package/lib/objection-js/objection-js-driver.js +4 -1
- package/lib/objection-js/objection-js-models-generation.js +98 -0
- package/lib/objection-js/objection-modules-loader.js +28 -0
- package/lib/objection-js/objection-modules-validator.js +31 -0
- package/lib/package-resolver.js +45 -0
- package/lib/prisma/prisma-client-loader.js +11 -1
- package/lib/prisma/prisma-driver.js +16 -2
- package/lib/prisma/prisma-filter-processor.js +5 -6
- package/lib/prisma/prisma-models-generation.js +236 -0
- package/lib/prisma/prisma-schema-generator.js +5 -1
- package/lib/prisma/prisma-type-caster.js +14 -0
- package/lib/query-builder-driver.js +210 -0
- package/lib/query-builder-models-generation.js +80 -0
- package/lib/relations-loader.js +192 -0
- package/lib/type-mapper.js +38 -0
- package/package.json +7 -7
- package/tests/.env.test.example +6 -0
- package/tests/fixtures/categories-fixtures.js +8 -0
- package/tests/fixtures/expected-entities/entities/test-product-details-entity.js +72 -0
- package/tests/fixtures/expected-entities/entities-config.js +6 -4
- package/tests/fixtures/expected-entities/entities-translations.js +25 -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-categories-model.js +13 -8
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js +80 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +20 -14
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +13 -12
- 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 +43 -0
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-products-model.js +2 -0
- package/tests/fixtures/product-details-fixtures.js +22 -0
- package/tests/fixtures/reviews-fixtures.js +2 -1
- package/tests/fixtures/sql/test-schema.sql +23 -1
- package/tests/fixtures/table-columns-fixtures.js +97 -0
- package/tests/integration/test-cross-driver-equivalence.js +286 -0
- package/tests/integration/test-nested-filters.js +265 -408
- package/tests/integration/test-relations.js +199 -0
- package/tests/integration/test-reldens-sample-data.js +255 -0
- package/tests/integration/test-reldens-shape-relations.js +292 -0
- package/tests/run-tests.js +112 -60
- package/tests/unit/test-drivers.js +7 -1
- package/tests/unit/test-models-generation.js +174 -0
- package/tests/utils/column-value-assert.js +139 -0
- package/tests/utils/driver-registry.js +1 -1
- package/tests/utils/entity-projection.js +111 -0
- package/tests/utils/observed-value.js +41 -0
- package/tests/utils/projection-difference.js +151 -0
- package/tests/utils/relations-shape-support.js +104 -0
- package/tests/utils/reldens-schema-loader.js +274 -0
- package/tests/utils/test-helpers.js +152 -19
- package/tests/utils/test-runner.js +26 -5
- package/tests/utils/whole-result-assert.js +243 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - QueryBuilderModelsGeneration
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { BaseGenerator } = require('./generators/base-generator');
|
|
8
|
+
const { sc } = require('@reldens/utils');
|
|
9
|
+
|
|
10
|
+
class QueryBuilderModelsGeneration extends BaseGenerator
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor(relationsDetection)
|
|
14
|
+
{
|
|
15
|
+
super();
|
|
16
|
+
this.relationsDetection = relationsDetection;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
modelTableName(tableName)
|
|
20
|
+
{
|
|
21
|
+
return tableName;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
generateEntityProperties(columns, tableName, tableData)
|
|
25
|
+
{
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
generateFkMappings(tableName, tableData)
|
|
30
|
+
{
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
generateIdColumn(columns)
|
|
35
|
+
{
|
|
36
|
+
let primaryKeyColumn = this.relationsDetection.detectPrimaryKeyColumn(columns);
|
|
37
|
+
if(!primaryKeyColumn){
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
if('id' === primaryKeyColumn){
|
|
41
|
+
return '';
|
|
42
|
+
}
|
|
43
|
+
return '\n static get idColumn()\n {\n return \''+primaryKeyColumn+'\';\n }\n';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
generateRelations(tableName, tableData, relationMetadata)
|
|
47
|
+
{
|
|
48
|
+
let allRelations = Object.assign(
|
|
49
|
+
{},
|
|
50
|
+
this.relationsDetection.detectForwardRelations(tableName, tableData),
|
|
51
|
+
this.relationsDetection.detectReverseRelations(tableName)
|
|
52
|
+
);
|
|
53
|
+
let relationKeys = Object.keys(allRelations);
|
|
54
|
+
if(0 === relationKeys.length){
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
let relationMappings = [];
|
|
58
|
+
for(let relationKey of relationKeys){
|
|
59
|
+
relationMappings.push(this.relationMappingDefinition(relationKey, allRelations[relationKey]));
|
|
60
|
+
}
|
|
61
|
+
return '\n static get relationMappings()\n {\n return {\n'
|
|
62
|
+
+relationMappings.join(',\n')
|
|
63
|
+
+'\n };\n }';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
relationMappingDefinition(relationKey, relation)
|
|
67
|
+
{
|
|
68
|
+
let relatedTable = sc.get(relation, 'referencedTable', relation.referencingTable);
|
|
69
|
+
let relationMapping = ' '+relationKey+': {\n';
|
|
70
|
+
relationMapping += ' relation: \''+relation.relationType+'\',\n';
|
|
71
|
+
relationMapping += ' tableName: \''+relatedTable+'\',\n';
|
|
72
|
+
relationMapping += ' from: \''+relation.fromColumn+'\',\n';
|
|
73
|
+
relationMapping += ' to: \''+relation.toColumn+'\'\n';
|
|
74
|
+
relationMapping += ' }';
|
|
75
|
+
return relationMapping;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports.QueryBuilderModelsGeneration = QueryBuilderModelsGeneration;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - RelationsLoader
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class RelationsLoader
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor(props)
|
|
13
|
+
{
|
|
14
|
+
this.driver = sc.get(props, 'driver', false);
|
|
15
|
+
this.server = sc.get(props, 'server', false);
|
|
16
|
+
this.relationMappings = sc.get(this.driver.rawModel, 'relationMappings', {});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
normalizeRelations(relations)
|
|
20
|
+
{
|
|
21
|
+
if(sc.isString(relations)){
|
|
22
|
+
relations = this.driver.parseRelationsString(relations);
|
|
23
|
+
}
|
|
24
|
+
if(!sc.isArray(relations)){
|
|
25
|
+
return Object.keys(this.relationMappings);
|
|
26
|
+
}
|
|
27
|
+
if(0 === relations.length){
|
|
28
|
+
return Object.keys(this.relationMappings);
|
|
29
|
+
}
|
|
30
|
+
return relations;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
relatedDriver(mapping)
|
|
34
|
+
{
|
|
35
|
+
if(!this.server){
|
|
36
|
+
Logger.error('Missing server on relations loader for table: '+mapping.tableName);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
let entities = this.server.entityManager.entities;
|
|
40
|
+
for(let entityKey of Object.keys(entities)){
|
|
41
|
+
if(entities[entityKey].tableName() === mapping.tableName){
|
|
42
|
+
return entities[entityKey];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
Logger.error('Related entity not found for table: '+mapping.tableName);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async populate(result, relations)
|
|
50
|
+
{
|
|
51
|
+
if(!result){
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
let rows = sc.isArray(result) ? result : [result];
|
|
55
|
+
if(0 === rows.length){
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
for(let relationPath of this.normalizeRelations(relations)){
|
|
59
|
+
await this.populateRelation(rows, relationPath);
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async populateRelation(rows, relationPath)
|
|
65
|
+
{
|
|
66
|
+
let pathParts = relationPath.split('.');
|
|
67
|
+
let relationKey = pathParts.shift();
|
|
68
|
+
let mapping = sc.get(this.relationMappings, relationKey, false);
|
|
69
|
+
if(!mapping){
|
|
70
|
+
Logger.warning('Unknown relation "'+relationKey+'" on table "'+this.driver.tableName()+'".');
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
let relatedDriver = this.relatedDriver(mapping);
|
|
74
|
+
if(!relatedDriver){
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
let relatedRows = await this.fetchRelatedRows(rows, mapping, relatedDriver);
|
|
78
|
+
this.assignRelatedRows(rows, relatedRows, mapping, relationKey);
|
|
79
|
+
if(0 === pathParts.length){
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if(0 === relatedRows.length){
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
await relatedDriver.relationsLoader.populate(relatedRows, [pathParts.join('.')]);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async fetchRelatedRows(rows, mapping, relatedDriver)
|
|
90
|
+
{
|
|
91
|
+
let values = [...new Set(
|
|
92
|
+
rows.map(row => row[mapping.from]).filter(value => sc.isNumber(value) || sc.isString(value))
|
|
93
|
+
)];
|
|
94
|
+
if(0 === values.length){
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
return await relatedDriver.selectRows(
|
|
98
|
+
{[mapping.to]: {operator: 'IN', value: values}},
|
|
99
|
+
Object.assign(relatedDriver.selectOptions(false), {offset: 0})
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
assignRelatedRows(rows, relatedRows, mapping, relationKey)
|
|
104
|
+
{
|
|
105
|
+
let isMany = 'HasManyRelation' === mapping.relation;
|
|
106
|
+
for(let row of rows){
|
|
107
|
+
let matches = relatedRows.filter(relatedRow => relatedRow[mapping.to] === row[mapping.from]);
|
|
108
|
+
if(isMany){
|
|
109
|
+
row[relationKey] = matches;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
row[relationKey] = matches.shift() || null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
extractNestedRelations(params, relations)
|
|
117
|
+
{
|
|
118
|
+
let nested = {};
|
|
119
|
+
for(let relationKey of this.normalizeRelations(relations)){
|
|
120
|
+
if(!sc.hasOwn(this.relationMappings, relationKey)){
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if(!sc.hasOwn(params, relationKey)){
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
nested[relationKey] = params[relationKey];
|
|
127
|
+
}
|
|
128
|
+
return nested;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async createWithRelations(params, relations)
|
|
132
|
+
{
|
|
133
|
+
let nested = this.extractNestedRelations(params, relations);
|
|
134
|
+
let nestedKeys = Object.keys(nested);
|
|
135
|
+
if(0 === nestedKeys.length){
|
|
136
|
+
return await this.driver.create(params);
|
|
137
|
+
}
|
|
138
|
+
let data = sc.omitProps(params, nestedKeys);
|
|
139
|
+
await this.createParents(data, nested);
|
|
140
|
+
let created = await this.driver.create(data);
|
|
141
|
+
if(!created){
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
await this.createChildren(created, nested);
|
|
145
|
+
return await this.populate(created, nestedKeys);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async createParents(data, nested)
|
|
149
|
+
{
|
|
150
|
+
for(let relationKey of Object.keys(nested)){
|
|
151
|
+
let mapping = sc.get(this.relationMappings, relationKey, false);
|
|
152
|
+
if('BelongsToOneRelation' !== mapping.relation){
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
let relatedDriver = this.relatedDriver(mapping);
|
|
156
|
+
if(!relatedDriver){
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
let parent = await relatedDriver.create(nested[relationKey]);
|
|
160
|
+
if(!parent){
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
data[mapping.from] = parent[mapping.to];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async createChildren(created, nested)
|
|
168
|
+
{
|
|
169
|
+
for(let relationKey of Object.keys(nested)){
|
|
170
|
+
let mapping = sc.get(this.relationMappings, relationKey, false);
|
|
171
|
+
if('BelongsToOneRelation' === mapping.relation){
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
let relatedDriver = this.relatedDriver(mapping);
|
|
175
|
+
if(!relatedDriver){
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
await this.createChildRows(created, nested[relationKey], mapping, relatedDriver);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async createChildRows(created, children, mapping, relatedDriver)
|
|
183
|
+
{
|
|
184
|
+
let childRows = sc.isArray(children) ? children : [children];
|
|
185
|
+
for(let childRow of childRows){
|
|
186
|
+
await relatedDriver.create(Object.assign({}, childRow, {[mapping.to]: created[mapping.from]}));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
module.exports.RelationsLoader = RelationsLoader;
|
package/lib/type-mapper.js
CHANGED
|
@@ -81,6 +81,44 @@ class TypeMapper
|
|
|
81
81
|
return typeMap[dbType.toLowerCase()] || 'String';
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
mapDbTypeToDrizzleBuilder(dbType)
|
|
85
|
+
{
|
|
86
|
+
let typeMap = {
|
|
87
|
+
'int': 'int',
|
|
88
|
+
'integer': 'int',
|
|
89
|
+
'tinyint': 'tinyint',
|
|
90
|
+
'smallint': 'smallint',
|
|
91
|
+
'mediumint': 'mediumint',
|
|
92
|
+
'bigint': 'bigint',
|
|
93
|
+
'decimal': 'decimal',
|
|
94
|
+
'float': 'float',
|
|
95
|
+
'double': 'double',
|
|
96
|
+
'varchar': 'varchar',
|
|
97
|
+
'char': 'char',
|
|
98
|
+
'text': 'text',
|
|
99
|
+
'tinytext': 'text',
|
|
100
|
+
'mediumtext': 'text',
|
|
101
|
+
'longtext': 'text',
|
|
102
|
+
'date': 'date',
|
|
103
|
+
'datetime': 'datetime',
|
|
104
|
+
'timestamp': 'timestamp',
|
|
105
|
+
'time': 'time',
|
|
106
|
+
'year': 'year',
|
|
107
|
+
'boolean': 'boolean',
|
|
108
|
+
'bool': 'boolean',
|
|
109
|
+
'bit': 'binary',
|
|
110
|
+
'json': 'json',
|
|
111
|
+
'enum': 'mysqlEnum',
|
|
112
|
+
'binary': 'binary',
|
|
113
|
+
'varbinary': 'varbinary',
|
|
114
|
+
'blob': 'binary',
|
|
115
|
+
'tinyblob': 'binary',
|
|
116
|
+
'mediumblob': 'binary',
|
|
117
|
+
'longblob': 'binary'
|
|
118
|
+
};
|
|
119
|
+
return typeMap[dbType.toLowerCase()] || 'text';
|
|
120
|
+
}
|
|
121
|
+
|
|
84
122
|
}
|
|
85
123
|
|
|
86
124
|
module.exports.TypeMapper = new TypeMapper();
|
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.118.0",
|
|
5
5
|
"description": "Reldens - Storage",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
"mikro-orm",
|
|
28
28
|
"prisma",
|
|
29
29
|
"prisma-orm",
|
|
30
|
+
"knex",
|
|
31
|
+
"kysely",
|
|
32
|
+
"drizzle",
|
|
33
|
+
"drizzle-orm",
|
|
34
|
+
"query-builder",
|
|
30
35
|
"driver",
|
|
31
36
|
"orm",
|
|
32
37
|
"database",
|
|
@@ -51,14 +56,9 @@
|
|
|
51
56
|
"test:driver": "node tests/run-tests.js --driver="
|
|
52
57
|
},
|
|
53
58
|
"dependencies": {
|
|
54
|
-
"@mikro-orm/core": "7.2.0",
|
|
55
|
-
"@mikro-orm/mongodb": "7.2.0",
|
|
56
|
-
"@mikro-orm/mysql": "7.2.0",
|
|
57
59
|
"@reldens/server-utils": "^0.57.0",
|
|
58
60
|
"@reldens/utils": "^0.58.0",
|
|
59
61
|
"knex": "3.3.0",
|
|
60
|
-
"
|
|
61
|
-
"mysql2": "3.24.3",
|
|
62
|
-
"objection": "3.1.5"
|
|
62
|
+
"mysql2": "3.24.4"
|
|
63
63
|
}
|
|
64
64
|
}
|
package/tests/.env.test.example
CHANGED
|
@@ -5,4 +5,10 @@ RELDENS_TEST_DB_PASSWORD=test_password
|
|
|
5
5
|
RELDENS_TEST_DB_NAME=reldens_storage_test
|
|
6
6
|
RELDENS_TEST_DB_CLIENT=mysql
|
|
7
7
|
RELDENS_DB_URL=mysql://test_user:test_password@localhost:3306/reldens_storage_test
|
|
8
|
+
RELDENS_TEST_OBJECTION_ENABLED=0
|
|
9
|
+
RELDENS_TEST_MIKRO_ORM_ENABLED=0
|
|
8
10
|
RELDENS_TEST_PRISMA_ENABLED=0
|
|
11
|
+
RELDENS_TEST_KYSELY_ENABLED=0
|
|
12
|
+
RELDENS_TEST_DRIZZLE_ENABLED=0
|
|
13
|
+
RELDENS_TEST_MIGRATIONS_PATH=
|
|
14
|
+
RELDENS_TEST_RELDENS_DB_NAME=reldens_storage_test_full
|
|
@@ -154,6 +154,14 @@ module.exports.CategoriesFixtures = {
|
|
|
154
154
|
display_order: 2,
|
|
155
155
|
slug: 'relations-test-2'
|
|
156
156
|
},
|
|
157
|
+
category_cross_driver_create: {
|
|
158
|
+
id: 1700,
|
|
159
|
+
name: 'Cross Driver Create',
|
|
160
|
+
description: 'Category created with the same explicit id by every driver',
|
|
161
|
+
is_active: 1,
|
|
162
|
+
display_order: 7,
|
|
163
|
+
slug: 'cross-driver-create'
|
|
164
|
+
},
|
|
157
165
|
category_create_nested: {
|
|
158
166
|
name: 'Nested Create Category',
|
|
159
167
|
description: 'Category for createWithRelations test',
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
customData: {
|
|
39
|
+
type: 'textarea',
|
|
40
|
+
dbType: 'text'
|
|
41
|
+
},
|
|
42
|
+
useTimeOut: {
|
|
43
|
+
type: 'number',
|
|
44
|
+
dbType: 'int'
|
|
45
|
+
},
|
|
46
|
+
created_at: {
|
|
47
|
+
type: 'datetime',
|
|
48
|
+
dbType: 'timestamp'
|
|
49
|
+
},
|
|
50
|
+
updated_at: {
|
|
51
|
+
type: 'datetime',
|
|
52
|
+
dbType: 'timestamp'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
let propertiesKeys = Object.keys(properties);
|
|
56
|
+
let showProperties = propertiesKeys;
|
|
57
|
+
let editProperties = sc.removeFromArray([...propertiesKeys], ['id', 'created_at', 'updated_at']);
|
|
58
|
+
let listProperties = [...propertiesKeys];
|
|
59
|
+
listProperties.splice(listProperties.indexOf('customData'), 1);
|
|
60
|
+
return {
|
|
61
|
+
showProperties,
|
|
62
|
+
editProperties,
|
|
63
|
+
listProperties,
|
|
64
|
+
filterProperties: listProperties,
|
|
65
|
+
properties,
|
|
66
|
+
...extraProps
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
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,16 @@ 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
|
+
'customData': 'CustomData',
|
|
31
|
+
'useTimeOut': 'UseTimeOut',
|
|
32
|
+
'created_at': 'Created At',
|
|
33
|
+
'updated_at': 'Updated At'
|
|
34
|
+
},
|
|
24
35
|
'test_products': {
|
|
25
36
|
'id': 'ID',
|
|
26
37
|
'category_id': 'Category ID',
|
|
@@ -48,6 +59,6 @@ module.exports.entitiesTranslations = {
|
|
|
48
59
|
'helpful_count': 'Helpful Count',
|
|
49
60
|
'created_at': 'Created At',
|
|
50
61
|
'updated_at': 'Updated At'
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
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-categories-model.js
CHANGED
|
@@ -34,14 +34,19 @@ const schema = new EntitySchema({
|
|
|
34
34
|
class: TestCategoriesModel,
|
|
35
35
|
tableName: 'test_categories',
|
|
36
36
|
properties: {
|
|
37
|
-
id: { type: '
|
|
38
|
-
name: { type: '
|
|
39
|
-
slug: { type: '
|
|
40
|
-
description: { type: '
|
|
41
|
-
is_active: { type: '
|
|
42
|
-
display_order: { type: '
|
|
43
|
-
created_at: { type: '
|
|
44
|
-
updated_at: { type: '
|
|
37
|
+
id: { type: 'int', primary: true },
|
|
38
|
+
name: { type: 'varchar' },
|
|
39
|
+
slug: { type: 'varchar' },
|
|
40
|
+
description: { type: 'text', nullable: true },
|
|
41
|
+
is_active: { type: 'tinyint', nullable: true },
|
|
42
|
+
display_order: { type: 'int', nullable: true },
|
|
43
|
+
created_at: { type: 'timestamp', nullable: true },
|
|
44
|
+
updated_at: { type: 'timestamp', nullable: true },
|
|
45
|
+
related_test_product_details: {
|
|
46
|
+
kind: '1:m',
|
|
47
|
+
entity: () => require('./test-product-details-model').TestProductDetailsModel,
|
|
48
|
+
mappedBy: 'related_test_categories'
|
|
49
|
+
},
|
|
45
50
|
related_test_products: {
|
|
46
51
|
kind: '1:m',
|
|
47
52
|
entity: () => require('./test-products-model').TestProductsModel,
|
package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
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, customData, useTimeOut, category_id, 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.customData = customData;
|
|
20
|
+
this.useTimeOut = useTimeOut;
|
|
21
|
+
this.category_id = category_id;
|
|
22
|
+
this.created_at = created_at;
|
|
23
|
+
this.updated_at = updated_at;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static createByProps(props)
|
|
27
|
+
{
|
|
28
|
+
const {id, product_id, weight, dimensions, customData, useTimeOut, category_id, created_at, updated_at} = props;
|
|
29
|
+
return new this(id, product_id, weight, dimensions, customData, useTimeOut, category_id, created_at, updated_at);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const schema = new EntitySchema({
|
|
35
|
+
class: TestProductDetailsModel,
|
|
36
|
+
tableName: 'test_product_details',
|
|
37
|
+
properties: {
|
|
38
|
+
id: { type: 'int', primary: true },
|
|
39
|
+
product_id: { type: 'int' },
|
|
40
|
+
weight: { type: 'decimal', nullable: true },
|
|
41
|
+
dimensions: { type: 'varchar', nullable: true },
|
|
42
|
+
customData: { type: 'text', nullable: true },
|
|
43
|
+
useTimeOut: { type: 'int', nullable: true },
|
|
44
|
+
category_id: { type: 'int', nullable: true },
|
|
45
|
+
created_at: { type: 'timestamp', nullable: true },
|
|
46
|
+
updated_at: { type: 'timestamp', nullable: true },
|
|
47
|
+
related_test_products: {
|
|
48
|
+
kind: '1:1',
|
|
49
|
+
entity: () => require('./test-products-model').TestProductsModel,
|
|
50
|
+
joinColumns: ['product_id'],
|
|
51
|
+
persist: false
|
|
52
|
+
},
|
|
53
|
+
related_test_categories: {
|
|
54
|
+
kind: 'm:1',
|
|
55
|
+
entity: () => require('./test-categories-model').TestCategoriesModel,
|
|
56
|
+
joinColumns: ['category_id'],
|
|
57
|
+
nullable: true,
|
|
58
|
+
persist: false
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
schema._fkMappings = {
|
|
63
|
+
"product_id": {
|
|
64
|
+
"relationKey": "related_test_products",
|
|
65
|
+
"entityName": "TestProductsModel",
|
|
66
|
+
"referencedColumn": "id",
|
|
67
|
+
"nullable": false
|
|
68
|
+
},
|
|
69
|
+
"category_id": {
|
|
70
|
+
"relationKey": "related_test_categories",
|
|
71
|
+
"entityName": "TestCategoriesModel",
|
|
72
|
+
"referencedColumn": "id",
|
|
73
|
+
"nullable": true
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
module.exports = {
|
|
77
|
+
TestProductDetailsModel,
|
|
78
|
+
entity: TestProductDetailsModel,
|
|
79
|
+
schema: schema
|
|
80
|
+
};
|