@reldens/storage 0.117.0 → 0.119.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 (78) hide show
  1. package/.claude/test-architecture.md +27 -17
  2. package/CLAUDE.md +67 -11
  3. package/README.md +204 -22
  4. package/bin/reldens-storage.js +43 -10
  5. package/index.js +53 -12
  6. package/lib/drizzle/drizzle-data-server.js +123 -0
  7. package/lib/drizzle/drizzle-driver.js +228 -0
  8. package/lib/drizzle/drizzle-models-generation.js +49 -0
  9. package/lib/drizzle/drizzle-modules-loader.js +32 -0
  10. package/lib/drizzle/drizzle-modules-validator.js +74 -0
  11. package/lib/entities-generator.js +36 -7
  12. package/lib/entity-templates/drizzle-model.template +28 -0
  13. package/lib/entity-templates/query-builder-model.template +17 -0
  14. package/lib/generators/base-generator.js +13 -0
  15. package/lib/generators/entities-generation.js +0 -13
  16. package/lib/generators/models-generation.js +179 -680
  17. package/lib/generators/relations-detection.js +171 -0
  18. package/lib/knex/knex-data-server.js +128 -0
  19. package/lib/knex/knex-driver.js +157 -0
  20. package/lib/knex/knex-modules-loader.js +28 -0
  21. package/lib/knex/knex-modules-validator.js +45 -0
  22. package/lib/kysely/kysely-data-server.js +128 -0
  23. package/lib/kysely/kysely-driver.js +176 -0
  24. package/lib/kysely/kysely-modules-loader.js +28 -0
  25. package/lib/kysely/kysely-modules-validator.js +53 -0
  26. package/lib/mikro-orm/mikro-orm-data-server.js +48 -29
  27. package/lib/mikro-orm/mikro-orm-driver.js +317 -108
  28. package/lib/mikro-orm/mikro-orm-models-generation.js +178 -0
  29. package/lib/mikro-orm/mikro-orm-modules-loader.js +50 -0
  30. package/lib/mikro-orm/mikro-orm-modules-validator.js +46 -0
  31. package/lib/mysql2-connection-config.js +38 -0
  32. package/lib/objection-js/objection-js-data-server.js +71 -125
  33. package/lib/objection-js/objection-js-driver.js +4 -1
  34. package/lib/objection-js/objection-js-models-generation.js +98 -0
  35. package/lib/objection-js/objection-modules-loader.js +28 -0
  36. package/lib/objection-js/objection-modules-validator.js +31 -0
  37. package/lib/package-resolver.js +45 -0
  38. package/lib/prisma/prisma-client-loader.js +11 -1
  39. package/lib/prisma/prisma-driver.js +16 -2
  40. package/lib/prisma/prisma-filter-processor.js +5 -6
  41. package/lib/prisma/prisma-models-generation.js +236 -0
  42. package/lib/prisma/prisma-schema-generator.js +5 -1
  43. package/lib/prisma/prisma-type-caster.js +14 -0
  44. package/lib/query-builder-driver.js +210 -0
  45. package/lib/query-builder-models-generation.js +80 -0
  46. package/lib/relations-loader.js +192 -0
  47. package/lib/type-mapper.js +38 -0
  48. package/package.json +8 -8
  49. package/tests/.env.test.example +6 -0
  50. package/tests/fixtures/categories-fixtures.js +8 -0
  51. package/tests/fixtures/expected-entities/entities/test-product-details-entity.js +10 -1
  52. package/tests/fixtures/expected-entities/entities-translations.js +2 -0
  53. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +13 -8
  54. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js +30 -10
  55. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +15 -14
  56. package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +13 -12
  57. package/tests/fixtures/expected-entities-prisma/models/prisma/test-product-details-model.js +3 -1
  58. package/tests/fixtures/product-details-fixtures.js +4 -1
  59. package/tests/fixtures/reviews-fixtures.js +2 -1
  60. package/tests/fixtures/sql/test-schema.sql +11 -2
  61. package/tests/fixtures/table-columns-fixtures.js +97 -0
  62. package/tests/integration/test-cross-driver-equivalence.js +286 -0
  63. package/tests/integration/test-nested-filters.js +265 -408
  64. package/tests/integration/test-relations.js +135 -0
  65. package/tests/integration/test-reldens-sample-data.js +255 -0
  66. package/tests/integration/test-reldens-shape-relations.js +292 -0
  67. package/tests/run-tests.js +111 -65
  68. package/tests/unit/test-drivers.js +7 -1
  69. package/tests/unit/test-models-generation.js +28 -18
  70. package/tests/utils/column-value-assert.js +139 -0
  71. package/tests/utils/entity-projection.js +111 -0
  72. package/tests/utils/observed-value.js +41 -0
  73. package/tests/utils/projection-difference.js +151 -0
  74. package/tests/utils/relations-shape-support.js +104 -0
  75. package/tests/utils/reldens-schema-loader.js +274 -0
  76. package/tests/utils/test-helpers.js +143 -13
  77. package/tests/utils/test-runner.js +26 -5
  78. package/tests/utils/whole-result-assert.js +243 -0
@@ -0,0 +1,178 @@
1
+ /**
2
+ *
3
+ * Reldens - MikroOrmModelsGeneration
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ class MikroOrmModelsGeneration
10
+ {
11
+
12
+ constructor(relationsDetection)
13
+ {
14
+ this.relationsDetection = relationsDetection;
15
+ this.relationKindMap = {
16
+ 'BelongsToOneRelation': 'm:1',
17
+ 'HasOneRelation': '1:1',
18
+ 'HasManyRelation': '1:m',
19
+ 'ManyToManyRelation': 'm:n'
20
+ };
21
+ this.columnTypesMap = {
22
+ 'bigint': 'number'
23
+ };
24
+ }
25
+
26
+ modelTableName(tableName)
27
+ {
28
+ return tableName;
29
+ }
30
+
31
+ generateRelations(tableName, tableData, relationMetadata)
32
+ {
33
+ return '';
34
+ }
35
+
36
+ generateIdColumn(columns)
37
+ {
38
+ return '';
39
+ }
40
+
41
+ generateEntityProperties(columns, tableName, tableData)
42
+ {
43
+ if(!tableName || !tableData){
44
+ return this.columnsProperties(columns, {}).join(',\n ');
45
+ }
46
+ let relations = this.relationsDetection.detectForwardRelations(tableName, tableData);
47
+ let entityProps = this.columnsProperties(columns);
48
+ for(let relationKey of Object.keys(relations)){
49
+ entityProps.push(this.forwardRelationProperty(relationKey, relations[relationKey], columns));
50
+ }
51
+ let reverseRelations = this.relationsDetection.detectReverseRelations(tableName);
52
+ for(let relationKey of Object.keys(reverseRelations)){
53
+ entityProps.push(this.reverseRelationProperty(relationKey, reverseRelations[relationKey], tableName));
54
+ }
55
+ return entityProps.join(',\n ');
56
+ }
57
+
58
+ columnsProperties(columns)
59
+ {
60
+ let entityProps = [];
61
+ for(let columnName of Object.keys(columns)){
62
+ entityProps.push(this.columnProperty(columnName, columns[columnName]));
63
+ }
64
+ return entityProps;
65
+ }
66
+
67
+ columnProperty(columnName, column)
68
+ {
69
+ let propDef = columnName+': { type: \''+sc.get(this.columnTypesMap, column.type, column.type)+'\'';
70
+ if('PRI' === column.key){
71
+ propDef += ', primary: true';
72
+ }
73
+ if('UNI' === column.key){
74
+ propDef += ', unique: true';
75
+ }
76
+ if(column.nullable || this.hasDefaultValue(column)){
77
+ propDef += ', nullable: true';
78
+ }
79
+ return propDef+' }';
80
+ }
81
+
82
+ hasDefaultValue(column)
83
+ {
84
+ return null !== column.default && 'undefined' !== typeof column.default;
85
+ }
86
+
87
+ forwardRelationProperty(relationKey, relation, columns)
88
+ {
89
+ let relatedModelClass = sc.capitalizedCamelCase(relation.referencedTable)+'Model';
90
+ let relatedModelFile = sc.kebabCase(relation.referencedTable)+'-model';
91
+ let propDef = relationKey+': {\n';
92
+ propDef += ' kind: \''+this.forwardRelationKind(columns[relation.fromColumn])+'\',\n';
93
+ propDef += ' entity: () => require(\'./'+relatedModelFile+'\').'+relatedModelClass;
94
+ if(relation.fromColumn){
95
+ propDef += ',\n joinColumns: [\''+relation.fromColumn+'\']';
96
+ }
97
+ if(this.isNonPrimaryReference(relation)){
98
+ propDef += ',\n referencedColumnNames: [\''+relation.toColumn+'\']';
99
+ propDef += ',\n targetKey: \''+relation.toColumn+'\'';
100
+ propDef += ',\n cascade: [],\n mapToPk: true';
101
+ }
102
+ if(this.isNullableColumn(columns[relation.fromColumn])){
103
+ propDef += ',\n nullable: true';
104
+ }
105
+ propDef += ',\n persist: false';
106
+ return propDef+'\n }';
107
+ }
108
+
109
+ isNonPrimaryReference(relation)
110
+ {
111
+ if(!relation.toColumn){
112
+ return false;
113
+ }
114
+ return 'id' !== relation.toColumn;
115
+ }
116
+
117
+ isNullableColumn(column)
118
+ {
119
+ if(!column){
120
+ return false;
121
+ }
122
+ return Boolean(column.nullable);
123
+ }
124
+
125
+ forwardRelationKind(column)
126
+ {
127
+ if('HasOneRelation' === this.relationsDetection.determineRelationType(column, false)){
128
+ return this.relationKindMap.HasOneRelation;
129
+ }
130
+ return this.relationKindMap.BelongsToOneRelation;
131
+ }
132
+
133
+ reverseRelationProperty(relationKey, relation, tableName)
134
+ {
135
+ let relatedModelClass = sc.capitalizedCamelCase(relation.referencingTable)+'Model';
136
+ let relatedModelFile = sc.kebabCase(relation.referencingTable)+'-model';
137
+ let mappedBy = this.relationsDetection.findMappedByKey(tableName, relation.referencingTable, relation);
138
+ let propDef = relationKey+': {\n';
139
+ propDef += ' kind: \''+sc.get(this.relationKindMap, relation.relationType, '1:m')+'\',\n';
140
+ propDef += ' entity: () => require(\'./'+relatedModelFile+'\').'+relatedModelClass;
141
+ if(mappedBy){
142
+ propDef += ',\n mappedBy: \''+mappedBy+'\'';
143
+ }
144
+ return propDef+'\n }';
145
+ }
146
+
147
+ generateFkMappings(tableName, tableData)
148
+ {
149
+ if(!tableName || !tableData){
150
+ return '';
151
+ }
152
+ let fkMappings = {};
153
+ let referenceCounts = this.relationsDetection.countReferencesPerTable(tableData);
154
+ for(let columnName of Object.keys(tableData.columns)){
155
+ let column = tableData.columns[columnName];
156
+ if(!sc.hasOwn(column, 'referencedTable')){
157
+ continue;
158
+ }
159
+ fkMappings[columnName] = {
160
+ relationKey: this.relationsDetection.generateForwardRelationKey(
161
+ column.referencedTable,
162
+ columnName,
163
+ referenceCounts
164
+ ),
165
+ entityName: sc.capitalizedCamelCase(column.referencedTable)+'Model',
166
+ referencedColumn: column.referencedColumn,
167
+ nullable: sc.get(column, 'nullable', false)
168
+ };
169
+ }
170
+ if(0 === Object.keys(fkMappings).length){
171
+ return '';
172
+ }
173
+ return JSON.stringify(fkMappings, null, 4);
174
+ }
175
+
176
+ }
177
+
178
+ module.exports.MikroOrmModelsGeneration = MikroOrmModelsGeneration;
@@ -0,0 +1,50 @@
1
+ /**
2
+ *
3
+ * Reldens - Storage - MikroOrmModulesLoader
4
+ *
5
+ */
6
+
7
+ const { MikroOrmModulesValidator } = require('./mikro-orm-modules-validator');
8
+ const { PackageResolver } = require('../package-resolver');
9
+
10
+ class MikroOrmModulesLoader
11
+ {
12
+
13
+ static load(projectPath, client)
14
+ {
15
+ let mikroOrmCore = PackageResolver.loadPackage('@mikro-orm/core', projectPath);
16
+ if(!mikroOrmCore){
17
+ return false;
18
+ }
19
+ let mikroOrmModules = {
20
+ MikroORM: mikroOrmCore.MikroORM,
21
+ EntityCaseNamingStrategy: mikroOrmCore.EntityCaseNamingStrategy,
22
+ Collection: mikroOrmCore.Collection,
23
+ EntitySchema: mikroOrmCore.EntitySchema
24
+ };
25
+ MikroOrmModulesLoader.appendClientDriver(mikroOrmModules, projectPath, client);
26
+ if(!MikroOrmModulesValidator.validate(mikroOrmModules, client)){
27
+ return false;
28
+ }
29
+ return mikroOrmModules;
30
+ }
31
+
32
+ static appendClientDriver(mikroOrmModules, projectPath, client)
33
+ {
34
+ if('mongodb' === client){
35
+ let mongoPackage = PackageResolver.loadPackage('@mikro-orm/mongodb', projectPath);
36
+ if(mongoPackage){
37
+ mikroOrmModules.MongoDriver = mongoPackage.MongoDriver;
38
+ }
39
+ return mikroOrmModules;
40
+ }
41
+ let mysqlPackage = PackageResolver.loadPackage('@mikro-orm/mysql', projectPath);
42
+ if(mysqlPackage){
43
+ mikroOrmModules.MySqlDriver = mysqlPackage.MySqlDriver;
44
+ }
45
+ return mikroOrmModules;
46
+ }
47
+
48
+ }
49
+
50
+ module.exports.MikroOrmModulesLoader = MikroOrmModulesLoader;
@@ -0,0 +1,46 @@
1
+ /**
2
+ *
3
+ * Reldens - MikroOrmModulesValidator
4
+ *
5
+ */
6
+
7
+ const { Logger, sc } = require('@reldens/utils');
8
+
9
+ let requiredCoreClasses = ['MikroORM', 'EntityCaseNamingStrategy', 'Collection'];
10
+
11
+ class MikroOrmModulesValidator
12
+ {
13
+
14
+ static validate(mikroOrmModules, client)
15
+ {
16
+ if(!sc.isObject(mikroOrmModules)){
17
+ Logger.critical('Missing "mikroOrmModules" object.');
18
+ return false;
19
+ }
20
+ let missingClasses = requiredCoreClasses.filter(coreClass => !sc.isFunction(mikroOrmModules[coreClass]));
21
+ if(0 < missingClasses.length){
22
+ Logger.critical('Invalid "mikroOrmModules", missing: '+missingClasses.join(', '));
23
+ return false;
24
+ }
25
+ return MikroOrmModulesValidator.validateClientDriver(mikroOrmModules, client);
26
+ }
27
+
28
+ static validateClientDriver(mikroOrmModules, client)
29
+ {
30
+ if('mongodb' === client){
31
+ if(!sc.isFunction(mikroOrmModules.MongoDriver)){
32
+ Logger.critical('Missing "mikroOrmModules.MongoDriver" for the "mongodb" client.');
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ if(!sc.isFunction(mikroOrmModules.MySqlDriver)){
38
+ Logger.critical('Missing "mikroOrmModules.MySqlDriver" for the "'+client+'" client.');
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ }
45
+
46
+ module.exports.MikroOrmModulesValidator = MikroOrmModulesValidator;
@@ -0,0 +1,38 @@
1
+ /**
2
+ *
3
+ * Reldens - Mysql2ConnectionConfig
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ let validMySQL2Options = [
10
+ 'authPlugins', 'authSwitchHandler', 'bigNumberStrings', 'charset', 'charsetNumber', 'compress',
11
+ 'connectAttributes', 'connectTimeout', 'database', 'dateStrings', 'debug', 'decimalNumbers',
12
+ 'enableKeepAlive', 'flags', 'host', 'insecureAuth', 'infileStreamFactory', 'isServer',
13
+ 'keepAliveInitialDelay', 'localAddress', 'maxPreparedStatements', 'multipleStatements',
14
+ 'namedPlaceholders', 'nestTables', 'password', 'password1', 'password2', 'password3', 'passwordSha1',
15
+ 'pool', 'port', 'queryFormat', 'rowsAsArray', 'socketPath', 'ssl', 'stream', 'stringifyObjects',
16
+ 'supportBigNumbers', 'timezone', 'trace', 'typeCast', 'uri', 'user', 'disableEval', 'connectionLimit',
17
+ 'maxIdle', 'idleTimeout', 'Promise', 'queueLimit', 'waitForConnections', 'jsonStrings', 'gracefulEnd'
18
+ ];
19
+
20
+ class Mysql2ConnectionConfig
21
+ {
22
+
23
+ static sanitize(config)
24
+ {
25
+ let cleanConfig = {};
26
+ for(let prop of validMySQL2Options){
27
+ if(sc.hasOwn(config, prop)){
28
+ cleanConfig[prop] = config[prop];
29
+ }
30
+ }
31
+ return cleanConfig;
32
+ }
33
+
34
+ }
35
+
36
+ module.exports.validMySQL2Options = validMySQL2Options;
37
+
38
+ module.exports.Mysql2ConnectionConfig = Mysql2ConnectionConfig;
@@ -1,125 +1,71 @@
1
- /**
2
- *
3
- * Reldens - ObjectionJsDataServer
4
- *
5
- */
6
-
7
- const { BaseDataServer } = require('../base-data-server');
8
- const { ObjectionJsDriver } = require('./objection-js-driver');
9
- const { MySQLTablesProvider } = require('../mysql-tables-provider');
10
- const { Model } = require('objection');
11
- const Knex = require('knex');
12
- const { Logger, sc } = require('@reldens/utils');
13
-
14
- class ObjectionJsDataServer extends BaseDataServer
15
- {
16
-
17
- constructor(props)
18
- {
19
- super(props);
20
- this.knex = false;
21
- if(!this.rawModel){
22
- this.rawModel = Model;
23
- }
24
- this.validMySQL2Options = [
25
- 'authPlugins', 'authSwitchHandler', 'bigNumberStrings', 'charset', 'charsetNumber', 'compress',
26
- 'connectAttributes', 'connectTimeout', 'database', 'dateStrings', 'debug', 'decimalNumbers',
27
- 'enableKeepAlive', 'flags', 'host', 'insecureAuth', 'infileStreamFactory', 'isServer',
28
- 'keepAliveInitialDelay', 'localAddress', 'maxPreparedStatements', 'multipleStatements',
29
- 'namedPlaceholders', 'nestTables', 'password', 'password1', 'password2', 'password3', 'passwordSha1',
30
- 'pool', 'port', 'queryFormat', 'rowsAsArray', 'socketPath', 'ssl', 'stream', 'stringifyObjects',
31
- 'supportBigNumbers', 'timezone', 'trace', 'typeCast', 'uri', 'user', 'disableEval', 'connectionLimit',
32
- 'maxIdle', 'idleTimeout', 'Promise', 'queueLimit', 'waitForConnections', 'jsonStrings', 'gracefulEnd'
33
- ];
34
- }
35
-
36
- async connect()
37
- {
38
- if(this.initialized){
39
- return this.initialized;
40
- }
41
- let connectionConfig = this.sanitizeConnectionConfig(this.config);
42
- this.knex = await Knex({
43
- client: this.client,
44
- connection: connectionConfig,
45
- pool: this.poolConfig,
46
- debug: this.debug,
47
- multipleStatements: this.multipleStatements
48
- });
49
- await this.rawModel.knex(this.knex);
50
- try {
51
- const [[{ currentTime }]] = await this.rawModel.knex().raw(
52
- 'SELECT ROUND(UNIX_TIMESTAMP(NOW(6)) * 1000 + MICROSECOND(NOW(6)) / 1000) AS currentTime;'
53
- );
54
- this.initialized = currentTime;
55
- } catch (err) {
56
- Logger.critical('Connection failed, Objection JS error.', err);
57
- }
58
- return this.initialized;
59
- }
60
-
61
- sanitizeConnectionConfig(config)
62
- {
63
- if('mysql2' !== this.client){
64
- return config;
65
- }
66
- let cleanConfig = {};
67
- for(let prop of this.validMySQL2Options){
68
- if(sc.hasOwn(config, prop)){
69
- cleanConfig[prop] = config[prop];
70
- }
71
- }
72
- return cleanConfig;
73
- }
74
-
75
- async disconnect()
76
- {
77
- if(!this.knex){
78
- return false;
79
- }
80
- await this.knex.destroy();
81
- return true;
82
- }
83
-
84
- generateEntities()
85
- {
86
- if(!this.rawEntities){
87
- Logger.warning('Empty raw entities array, none entities generated.');
88
- return {};
89
- }
90
- this.entities = {};
91
- for(let i of Object.keys(this.rawEntities)){
92
- let rawEntity = this.rawEntities[i];
93
- if(!rawEntity?.knex){
94
- Logger.critical('Invalid raw entity "'+i+'".');
95
- continue;
96
- }
97
- this.entities[i] = new ObjectionJsDriver({rawModel: rawEntity, id: i, name: i, config: rawEntity.knex});
98
- }
99
- this.entityManager.setEntities(this.entities);
100
- return this.entities;
101
- }
102
-
103
- name()
104
- {
105
- return this.name || 'Objection JS Data Server Driver';
106
- }
107
-
108
- async rawQuery(content)
109
- {
110
- let result = await this.knex.raw(content);
111
- return result[0] || false;
112
- }
113
-
114
- async fetchEntitiesFromDatabase()
115
- {
116
- if(!this.initialized){
117
- Logger.error('Connection was not initialized, please use the connect method first.');
118
- return false;
119
- }
120
- return await MySQLTablesProvider.fetchTables(this);
121
- }
122
-
123
- }
124
-
125
- module.exports.ObjectionJsDataServer = ObjectionJsDataServer;
1
+ /**
2
+ *
3
+ * Reldens - ObjectionJsDataServer
4
+ *
5
+ */
6
+
7
+ const { KnexDataServer } = require('../knex/knex-data-server');
8
+ const { ObjectionJsDriver } = require('./objection-js-driver');
9
+ const { ObjectionModulesValidator } = require('./objection-modules-validator');
10
+ const { ObjectionModulesLoader } = require('./objection-modules-loader');
11
+ const { Logger, sc } = require('@reldens/utils');
12
+
13
+ class ObjectionJsDataServer extends KnexDataServer
14
+ {
15
+
16
+ constructor(props)
17
+ {
18
+ super(props);
19
+ this.objectionModules = sc.get(props, 'objectionModules', false);
20
+ }
21
+
22
+ async connect()
23
+ {
24
+ if(!this.objectionModules){
25
+ this.objectionModules = ObjectionModulesLoader.load(this.projectRoot);
26
+ }
27
+ if(!ObjectionModulesValidator.validate(this.objectionModules)){
28
+ return false;
29
+ }
30
+ if(!this.rawModel){
31
+ this.rawModel = this.objectionModules.Model;
32
+ }
33
+ let initialized = await super.connect();
34
+ if(this.knex){
35
+ await this.rawModel.knex(this.knex);
36
+ }
37
+ return initialized;
38
+ }
39
+
40
+ connectionErrorMessage()
41
+ {
42
+ return 'Connection failed, Objection JS error.';
43
+ }
44
+
45
+ generateEntities()
46
+ {
47
+ if(!this.rawEntities){
48
+ Logger.warning('Empty raw entities array, none entities generated.');
49
+ return {};
50
+ }
51
+ this.entities = {};
52
+ for(let i of Object.keys(this.rawEntities)){
53
+ let rawEntity = this.rawEntities[i];
54
+ if(!rawEntity?.knex){
55
+ Logger.critical('Invalid raw entity "'+i+'".');
56
+ continue;
57
+ }
58
+ this.entities[i] = new ObjectionJsDriver({rawModel: rawEntity, id: i, name: i, config: rawEntity.knex});
59
+ }
60
+ this.entityManager.setEntities(this.entities);
61
+ return this.entities;
62
+ }
63
+
64
+ name()
65
+ {
66
+ return this.name || 'Objection JS Data Server Driver';
67
+ }
68
+
69
+ }
70
+
71
+ module.exports.ObjectionJsDataServer = ObjectionJsDataServer;
@@ -37,7 +37,7 @@ class ObjectionJsDriver extends BaseDriver
37
37
 
38
38
  create(params)
39
39
  {
40
- return this.queryBuilder().insert(params);
40
+ return this.queryBuilder().insertAndFetch(params);
41
41
  }
42
42
 
43
43
  createWithRelations(params, relations)
@@ -359,6 +359,9 @@ class ObjectionJsDriver extends BaseDriver
359
359
 
360
360
  appendRelationsToQuery(queryBuilder, relations, relationsModifiers, useJoin = false)
361
361
  {
362
+ if(sc.isString(relations)){
363
+ relations = this.parseRelationsString(relations);
364
+ }
362
365
  if(!sc.isArray(relations) || 0 === relations.length){
363
366
  relations = Object.keys(this.rawModel.relationMappings || {});
364
367
  }
@@ -0,0 +1,98 @@
1
+ /**
2
+ *
3
+ * Reldens - ObjectionJsModelsGeneration
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ class ObjectionJsModelsGeneration
10
+ {
11
+
12
+ constructor(relationsDetection)
13
+ {
14
+ this.relationsDetection = relationsDetection;
15
+ }
16
+
17
+ modelTableName(tableName)
18
+ {
19
+ return tableName;
20
+ }
21
+
22
+ generateEntityProperties(columns, tableName, tableData)
23
+ {
24
+ return '';
25
+ }
26
+
27
+ generateFkMappings(tableName, tableData)
28
+ {
29
+ return '';
30
+ }
31
+
32
+ generateIdColumn(columns)
33
+ {
34
+ let primaryKeyColumn = this.relationsDetection.detectPrimaryKeyColumn(columns);
35
+ if(!primaryKeyColumn || 'id' === primaryKeyColumn){
36
+ return '';
37
+ }
38
+ return '\n static get idColumn()\n {\n return \''+primaryKeyColumn+'\';\n }\n';
39
+ }
40
+
41
+ generateRelations(tableName, tableData, relationMetadata)
42
+ {
43
+ let relations = this.relationsDetection.detectForwardRelations(tableName, tableData);
44
+ let reverseRelations = this.relationsDetection.detectReverseRelations(tableName);
45
+ let allRelations = Object.assign({}, relations, reverseRelations);
46
+ if(0 === Object.keys(allRelations).length){
47
+ return '';
48
+ }
49
+ let relationMappings = [];
50
+ let requiredModels = [];
51
+ for(let relationKey of Object.keys(allRelations)){
52
+ let relation = allRelations[relationKey];
53
+ let tableReference = sc.get(relation, 'referencedTable', relation.referencingTable);
54
+ let relatedModelClass = sc.capitalizedCamelCase(tableReference)+'Model';
55
+ if(!requiredModels.find(requiredModel => requiredModel.modelClass === relatedModelClass)){
56
+ requiredModels.push({
57
+ modelClass: relatedModelClass,
58
+ fileName: sc.kebabCase(tableReference)+'-model'
59
+ });
60
+ }
61
+ relationMappings.push(this.relationMappingDefinition(relationKey, relation, relatedModelClass));
62
+ }
63
+ return this.relationMappingsMethod(requiredModels, relationMappings);
64
+ }
65
+
66
+ relationMappingDefinition(relationKey, relation, relatedModelClass)
67
+ {
68
+ let relationMapping = ' '+relationKey+': {\n';
69
+ relationMapping += ' relation: this.'+relation.relationType+',\n';
70
+ relationMapping += ' modelClass: '+relatedModelClass+',\n';
71
+ relationMapping += ' join: {\n';
72
+ relationMapping += ' from: this.tableName+\'.'+relation.fromColumn+'\',\n';
73
+ relationMapping += ' to: '+relatedModelClass+'.tableName+\'.'+relation.toColumn+'\'\n';
74
+ relationMapping += ' }\n';
75
+ relationMapping += ' }';
76
+ return relationMapping;
77
+ }
78
+
79
+ relationMappingsMethod(requiredModels, relationMappings)
80
+ {
81
+ let requireStatements = [];
82
+ for(let modelInfo of requiredModels){
83
+ requireStatements.push(
84
+ ' const { '+modelInfo.modelClass+' } = require(\'./'+modelInfo.fileName+'\');'
85
+ );
86
+ }
87
+ let relationMappingsMethod = '\n static get relationMappings()\n {\n';
88
+ relationMappingsMethod += requireStatements.join('\n')+'\n';
89
+ relationMappingsMethod += ' return {\n';
90
+ relationMappingsMethod += relationMappings.join(',\n');
91
+ relationMappingsMethod += '\n };\n';
92
+ relationMappingsMethod += ' }';
93
+ return relationMappingsMethod;
94
+ }
95
+
96
+ }
97
+
98
+ module.exports.ObjectionJsModelsGeneration = ObjectionJsModelsGeneration;
@@ -0,0 +1,28 @@
1
+ /**
2
+ *
3
+ * Reldens - Storage - ObjectionModulesLoader
4
+ *
5
+ */
6
+
7
+ const { ObjectionModulesValidator } = require('./objection-modules-validator');
8
+ const { PackageResolver } = require('../package-resolver');
9
+
10
+ class ObjectionModulesLoader
11
+ {
12
+
13
+ static load(projectPath)
14
+ {
15
+ let objection = PackageResolver.loadPackage('objection', projectPath);
16
+ if(!objection){
17
+ return false;
18
+ }
19
+ let objectionModules = {Model: objection.Model};
20
+ if(!ObjectionModulesValidator.validate(objectionModules)){
21
+ return false;
22
+ }
23
+ return objectionModules;
24
+ }
25
+
26
+ }
27
+
28
+ module.exports.ObjectionModulesLoader = ObjectionModulesLoader;