@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,171 @@
1
+ /**
2
+ *
3
+ * Reldens - RelationsDetection
4
+ *
5
+ */
6
+
7
+ const { RELATION_PREFIX } = require('../relation-key');
8
+ const { sc } = require('@reldens/utils');
9
+
10
+ class RelationsDetection
11
+ {
12
+
13
+ constructor(props)
14
+ {
15
+ this.allTablesData = {};
16
+ this.removeIdFromMultipleRelations = sc.get(props, 'removeIdFromMultipleRelations', true);
17
+ }
18
+
19
+ detectForwardRelations(tableName, tableData)
20
+ {
21
+ let relations = {};
22
+ let referenceCounts = this.countReferencesPerTable(tableData);
23
+ for(let columnName of Object.keys(tableData.columns)){
24
+ let column = tableData.columns[columnName];
25
+ if(!sc.hasOwn(column, 'referencedTable')){
26
+ continue;
27
+ }
28
+ let relationKey = this.generateForwardRelationKey(column.referencedTable, columnName, referenceCounts);
29
+ relations[relationKey] = {
30
+ fromColumn: columnName,
31
+ toColumn: column.referencedColumn,
32
+ referencedTable: column.referencedTable,
33
+ relationType: this.determineRelationType(column, true)
34
+ };
35
+ }
36
+ return relations;
37
+ }
38
+
39
+ detectReverseRelations(tableName)
40
+ {
41
+ let reverseRelations = {};
42
+ for(let otherTableName of Object.keys(this.allTablesData)){
43
+ if(otherTableName === tableName){
44
+ continue;
45
+ }
46
+ Object.assign(reverseRelations, this.detectTableReverseRelations(tableName, otherTableName));
47
+ }
48
+ return reverseRelations;
49
+ }
50
+
51
+ detectTableReverseRelations(tableName, otherTableName)
52
+ {
53
+ let reverseRelations = {};
54
+ let otherTableData = this.allTablesData[otherTableName];
55
+ let referenceCounts = this.countReferencesToTable(tableName, otherTableData);
56
+ for(let columnName of Object.keys(otherTableData.columns)){
57
+ let column = otherTableData.columns[columnName];
58
+ if(!sc.hasOwn(column, 'referencedTable')){
59
+ continue;
60
+ }
61
+ if(column.referencedTable !== tableName){
62
+ continue;
63
+ }
64
+ let relationKey = this.generateReverseRelationKey(otherTableName, columnName, referenceCounts);
65
+ reverseRelations[relationKey] = {
66
+ fromColumn: column.referencedColumn,
67
+ toColumn: columnName,
68
+ referencingTable: otherTableName,
69
+ relationType: this.determineRelationType(column, false)
70
+ };
71
+ }
72
+ return reverseRelations;
73
+ }
74
+
75
+ determineRelationType(column, isForwardRelation)
76
+ {
77
+ if(isForwardRelation){
78
+ return 'BelongsToOneRelation';
79
+ }
80
+ if('PRI' === column.key || 'UNI' === column.key){
81
+ return 'HasOneRelation';
82
+ }
83
+ return 'HasManyRelation';
84
+ }
85
+
86
+ countReferencesPerTable(tableData)
87
+ {
88
+ let counts = {};
89
+ for(let columnName of Object.keys(tableData.columns)){
90
+ let column = tableData.columns[columnName];
91
+ if(!sc.hasOwn(column, 'referencedTable')){
92
+ continue;
93
+ }
94
+ if(!counts[column.referencedTable]){
95
+ counts[column.referencedTable] = 0;
96
+ }
97
+ counts[column.referencedTable]++;
98
+ }
99
+ return counts;
100
+ }
101
+
102
+ countReferencesToTable(targetTable, sourceTableData)
103
+ {
104
+ let count = 0;
105
+ for(let columnName of Object.keys(sourceTableData.columns)){
106
+ let column = sourceTableData.columns[columnName];
107
+ if(!sc.hasOwn(column, 'referencedTable')){
108
+ continue;
109
+ }
110
+ if(column.referencedTable === targetTable){
111
+ count++;
112
+ }
113
+ }
114
+ return count;
115
+ }
116
+
117
+ generateForwardRelationKey(referencedTable, columnName, referenceCounts)
118
+ {
119
+ if(1 === referenceCounts[referencedTable]){
120
+ return RELATION_PREFIX+referencedTable;
121
+ }
122
+ return RELATION_PREFIX+referencedTable+'_'+this.relationKeyColumnSuffix(columnName);
123
+ }
124
+
125
+ generateReverseRelationKey(referencingTable, columnName, referenceCount)
126
+ {
127
+ if(1 === referenceCount){
128
+ return RELATION_PREFIX+referencingTable;
129
+ }
130
+ return RELATION_PREFIX+referencingTable+'_'+this.relationKeyColumnSuffix(columnName);
131
+ }
132
+
133
+ relationKeyColumnSuffix(columnName)
134
+ {
135
+ if(this.removeIdFromMultipleRelations){
136
+ return columnName.replace(/_id$/i, '');
137
+ }
138
+ return columnName;
139
+ }
140
+
141
+ findMappedByKey(currentTable, referencingTable, reverseRelation)
142
+ {
143
+ if(!this.allTablesData[referencingTable]){
144
+ return RELATION_PREFIX+currentTable;
145
+ }
146
+ let forwardRelations = this.detectForwardRelations(referencingTable, this.allTablesData[referencingTable]);
147
+ for(let forwardKey of Object.keys(forwardRelations)){
148
+ let forward = forwardRelations[forwardKey];
149
+ if(forward.referencedTable !== currentTable){
150
+ continue;
151
+ }
152
+ if(forward.fromColumn === reverseRelation.toColumn && forward.toColumn === reverseRelation.fromColumn){
153
+ return forwardKey;
154
+ }
155
+ }
156
+ return RELATION_PREFIX+currentTable;
157
+ }
158
+
159
+ detectPrimaryKeyColumn(columns)
160
+ {
161
+ for(let columnName of Object.keys(columns)){
162
+ if('PRI' === columns[columnName].key){
163
+ return columnName;
164
+ }
165
+ }
166
+ return null;
167
+ }
168
+
169
+ }
170
+
171
+ module.exports.RelationsDetection = RelationsDetection;
@@ -0,0 +1,128 @@
1
+ /**
2
+ *
3
+ * Reldens - KnexDataServer
4
+ *
5
+ */
6
+
7
+ const { BaseDataServer } = require('../base-data-server');
8
+ const { KnexDriver } = require('./knex-driver');
9
+ const { MySQLTablesProvider } = require('../mysql-tables-provider');
10
+ const { Mysql2ConnectionConfig } = require('../mysql2-connection-config');
11
+ const { KnexModulesValidator } = require('./knex-modules-validator');
12
+ const { KnexModulesLoader } = require('./knex-modules-loader');
13
+ const { Logger, sc } = require('@reldens/utils');
14
+
15
+ class KnexDataServer extends BaseDataServer
16
+ {
17
+
18
+ constructor(props)
19
+ {
20
+ super(props);
21
+ this.knexModules = sc.get(props, 'knexModules', false);
22
+ this.knex = sc.get(this.knexModules, 'knex', false);
23
+ }
24
+
25
+ async connect()
26
+ {
27
+ if(this.initialized){
28
+ return this.initialized;
29
+ }
30
+ if(!this.knexModules){
31
+ this.knexModules = KnexModulesLoader.load(this.projectRoot);
32
+ }
33
+ if(!KnexModulesValidator.validate(this.knexModules)){
34
+ return false;
35
+ }
36
+ if(!this.knex){
37
+ this.knex = await this.knexModules.Knex({
38
+ client: this.client,
39
+ connection: this.sanitizeConnectionConfig(this.config),
40
+ pool: this.poolConfig,
41
+ debug: this.debug,
42
+ multipleStatements: this.multipleStatements
43
+ });
44
+ this.knexModules.knex = this.knex;
45
+ }
46
+ try {
47
+ const [[{ currentTime }]] = await this.knex.raw(
48
+ 'SELECT ROUND(UNIX_TIMESTAMP(NOW(6)) * 1000 + MICROSECOND(NOW(6)) / 1000) AS currentTime;'
49
+ );
50
+ this.initialized = currentTime;
51
+ } catch(error) {
52
+ Logger.critical(this.connectionErrorMessage(), error);
53
+ }
54
+ return this.initialized;
55
+ }
56
+
57
+ connectionErrorMessage()
58
+ {
59
+ return 'Connection failed, Knex error.';
60
+ }
61
+
62
+ sanitizeConnectionConfig(config)
63
+ {
64
+ if('mysql2' !== this.client){
65
+ return config;
66
+ }
67
+ return Mysql2ConnectionConfig.sanitize(config);
68
+ }
69
+
70
+ async disconnect()
71
+ {
72
+ if(!this.knex){
73
+ return false;
74
+ }
75
+ await this.knex.destroy();
76
+ this.knex = false;
77
+ this.initialized = false;
78
+ return true;
79
+ }
80
+
81
+ generateEntities()
82
+ {
83
+ if(!this.rawEntities){
84
+ Logger.warning('Empty raw entities array, none entities generated.');
85
+ return {};
86
+ }
87
+ this.entities = {};
88
+ for(let i of Object.keys(this.rawEntities)){
89
+ let rawEntity = this.rawEntities[i];
90
+ if(!sc.isString(sc.get(rawEntity, 'tableName', false))){
91
+ Logger.critical('Invalid raw entity "'+i+'".');
92
+ continue;
93
+ }
94
+ this.entities[i] = new KnexDriver({
95
+ rawModel: rawEntity,
96
+ id: i,
97
+ name: i,
98
+ config: this.config,
99
+ server: this,
100
+ knex: this.knex
101
+ });
102
+ }
103
+ this.entityManager.setEntities(this.entities);
104
+ return this.entities;
105
+ }
106
+
107
+ name()
108
+ {
109
+ return this.name || 'Knex Data Server Driver';
110
+ }
111
+
112
+ async rawQuery(content)
113
+ {
114
+ return (await this.knex.raw(content)).shift() || false;
115
+ }
116
+
117
+ async fetchEntitiesFromDatabase()
118
+ {
119
+ if(!this.initialized){
120
+ Logger.error('Connection was not initialized, please use the connect method first.');
121
+ return false;
122
+ }
123
+ return await MySQLTablesProvider.fetchTables(this);
124
+ }
125
+
126
+ }
127
+
128
+ module.exports.KnexDataServer = KnexDataServer;
@@ -0,0 +1,157 @@
1
+ /**
2
+ *
3
+ * Reldens - KnexDriver
4
+ *
5
+ */
6
+
7
+ const { QueryBuilderDriver } = require('../query-builder-driver');
8
+ const { sc } = require('@reldens/utils');
9
+
10
+ class KnexDriver extends QueryBuilderDriver
11
+ {
12
+
13
+ constructor(props)
14
+ {
15
+ super(props);
16
+ this.knex = sc.get(props, 'knex', false);
17
+ }
18
+
19
+ queryBuilder()
20
+ {
21
+ return this.knex(this.tableName());
22
+ }
23
+
24
+ async insertRow(data)
25
+ {
26
+ return (await this.queryBuilder().insert(data)).shift() || 0;
27
+ }
28
+
29
+ selectRows(filters, options)
30
+ {
31
+ let query = this.queryBuilder();
32
+ this.appendFilters(query, filters);
33
+ if(0 < options.select.length){
34
+ query.select(...options.select);
35
+ }
36
+ if(0 < options.limit){
37
+ query.limit(options.limit);
38
+ }
39
+ if(0 < options.offset){
40
+ query.offset(options.offset);
41
+ }
42
+ if(options.sortBy && options.sortDirection){
43
+ query.orderBy(options.sortBy, options.sortDirection);
44
+ }
45
+ return query;
46
+ }
47
+
48
+ update(filters, updatePatch)
49
+ {
50
+ return this.appendFilters(this.queryBuilder(), filters).update(updatePatch);
51
+ }
52
+
53
+ delete(filters = {})
54
+ {
55
+ return this.appendFilters(this.queryBuilder(), filters).delete();
56
+ }
57
+
58
+ async count(filters = {})
59
+ {
60
+ let result = await this.appendFilters(this.queryBuilder(), filters).count('* as count').first();
61
+ if(!result){
62
+ return 0;
63
+ }
64
+ return Number(result.count);
65
+ }
66
+
67
+ appendFilters(query, filters = {})
68
+ {
69
+ for(let key of Object.keys(filters)){
70
+ this.appendFilter(query, key, filters[key]);
71
+ }
72
+ return query;
73
+ }
74
+
75
+ appendFilter(query, key, filter)
76
+ {
77
+ if('AND' === key && sc.isArray(filter)){
78
+ this.appendAndConditions(query, filter);
79
+ return;
80
+ }
81
+ if('OR' === key && sc.isArray(filter)){
82
+ this.appendOrConditions(query, filter);
83
+ return;
84
+ }
85
+ let operator = sc.get(filter, 'operator', '').toUpperCase();
86
+ if(operator){
87
+ this.appendOperatorFilter(query, key, operator, filter);
88
+ return;
89
+ }
90
+ if(sc.hasOwn(this.relationsLoader.relationMappings, key) && sc.isObject(filter)){
91
+ let mapping = this.relationsLoader.relationMappings[key];
92
+ query.whereIn(mapping.from, this.relationSubQuery(mapping, filter));
93
+ return;
94
+ }
95
+ query.where(key, filter);
96
+ }
97
+
98
+ appendAndConditions(query, conditions)
99
+ {
100
+ for(let condition of conditions){
101
+ query.where(nestedQuery => this.appendFilters(nestedQuery, condition));
102
+ }
103
+ }
104
+
105
+ appendOrConditions(query, conditions)
106
+ {
107
+ query.where(outerQuery => {
108
+ for(let condition of conditions){
109
+ outerQuery.orWhere(innerQuery => this.appendFilters(innerQuery, condition));
110
+ }
111
+ });
112
+ }
113
+
114
+ appendOperatorFilter(query, field, operator, filter)
115
+ {
116
+ if('OR' === operator){
117
+ query.orWhere(field, filter.value);
118
+ return;
119
+ }
120
+ if('IN' === operator){
121
+ query.whereIn(field, filter.value);
122
+ return;
123
+ }
124
+ if('NOT' === operator){
125
+ query.whereNot(field, filter.value);
126
+ return;
127
+ }
128
+ if('LIKE' === operator){
129
+ this.appendLikeFilter(query, field, filter.value);
130
+ return;
131
+ }
132
+ query.where(field, sc.get(this.operatorsMap, operator, filter.operator), filter.value);
133
+ }
134
+
135
+ appendLikeFilter(query, field, value)
136
+ {
137
+ let likeValue = '%'+String(value).replace(/%/g, '')+'%';
138
+ if(this.isJsonField(field)){
139
+ query.whereRaw('CAST(?? AS CHAR) LIKE ?', [field, likeValue]);
140
+ return;
141
+ }
142
+ query.where(field, 'like', likeValue);
143
+ }
144
+
145
+ relationSubQuery(mapping, nestedFilters)
146
+ {
147
+ let subQuery = this.knex(mapping.tableName).select(mapping.to);
148
+ let relatedDriver = this.relationsLoader.relatedDriver(mapping);
149
+ if(!relatedDriver){
150
+ return subQuery;
151
+ }
152
+ return relatedDriver.appendFilters(subQuery, nestedFilters);
153
+ }
154
+
155
+ }
156
+
157
+ module.exports.KnexDriver = KnexDriver;
@@ -0,0 +1,28 @@
1
+ /**
2
+ *
3
+ * Reldens - Storage - KnexModulesLoader
4
+ *
5
+ */
6
+
7
+ const { KnexModulesValidator } = require('./knex-modules-validator');
8
+ const { PackageResolver } = require('../package-resolver');
9
+
10
+ class KnexModulesLoader
11
+ {
12
+
13
+ static load(projectPath)
14
+ {
15
+ let knex = PackageResolver.loadPackage('knex', projectPath);
16
+ if(!knex){
17
+ return false;
18
+ }
19
+ let knexModules = {Knex: knex};
20
+ if(!KnexModulesValidator.validate(knexModules)){
21
+ return false;
22
+ }
23
+ return knexModules;
24
+ }
25
+
26
+ }
27
+
28
+ module.exports.KnexModulesLoader = KnexModulesLoader;
@@ -0,0 +1,45 @@
1
+ /**
2
+ *
3
+ * Reldens - KnexModulesValidator
4
+ *
5
+ */
6
+
7
+ const { Logger, sc } = require('@reldens/utils');
8
+
9
+ class KnexModulesValidator
10
+ {
11
+
12
+ static validate(knexModules)
13
+ {
14
+ if(!sc.isObject(knexModules)){
15
+ Logger.critical('Missing "knexModules" object.');
16
+ return false;
17
+ }
18
+ if(knexModules.knex){
19
+ return KnexModulesValidator.validateKnexInstance(knexModules.knex);
20
+ }
21
+ if(!sc.isFunction(knexModules.Knex)){
22
+ Logger.critical('Invalid "knexModules.Knex".');
23
+ return false;
24
+ }
25
+ return true;
26
+ }
27
+
28
+ static validateKnexInstance(knexInstance)
29
+ {
30
+ if(!sc.isFunction(knexInstance)){
31
+ Logger.critical('Invalid Knex instance, it must be callable.');
32
+ return false;
33
+ }
34
+ let requiredMethods = ['raw', 'destroy'];
35
+ let missingMethods = requiredMethods.filter(method => !sc.isFunction(knexInstance[method]));
36
+ if(0 < missingMethods.length){
37
+ Logger.critical('Invalid Knex instance, missing: '+missingMethods.join(', '));
38
+ return false;
39
+ }
40
+ return true;
41
+ }
42
+
43
+ }
44
+
45
+ module.exports.KnexModulesValidator = KnexModulesValidator;
@@ -0,0 +1,128 @@
1
+ /**
2
+ *
3
+ * Reldens - KyselyDataServer
4
+ *
5
+ */
6
+
7
+ const { BaseDataServer } = require('../base-data-server');
8
+ const { KyselyDriver } = require('./kysely-driver');
9
+ const { KyselyModulesValidator } = require('./kysely-modules-validator');
10
+ const { MySQLTablesProvider } = require('../mysql-tables-provider');
11
+ const { Mysql2ConnectionConfig } = require('../mysql2-connection-config');
12
+ const { createPool } = require('mysql2');
13
+ const { Logger, sc } = require('@reldens/utils');
14
+
15
+ class KyselyDataServer extends BaseDataServer
16
+ {
17
+
18
+ constructor(props)
19
+ {
20
+ super(props);
21
+ this.kyselyModules = sc.get(props, 'kyselyModules', false);
22
+ this.db = sc.get(this.kyselyModules, 'db', false);
23
+ }
24
+
25
+ async connect()
26
+ {
27
+ if(this.initialized){
28
+ return this.initialized;
29
+ }
30
+ if(!KyselyModulesValidator.validate(this.kyselyModules)){
31
+ return false;
32
+ }
33
+ try {
34
+ if(!this.db){
35
+ this.db = new this.kyselyModules.Kysely({
36
+ dialect: new this.kyselyModules.MysqlDialect({pool: createPool(this.poolConfiguration())})
37
+ });
38
+ this.kyselyModules.db = this.db;
39
+ }
40
+ await this.kyselyModules.sql.raw('SELECT 1').execute(this.db);
41
+ this.initialized = Date.now();
42
+ } catch(error) {
43
+ Logger.critical('Connection failed, Kysely error: '+error.message);
44
+ }
45
+ return this.initialized;
46
+ }
47
+
48
+ poolConfiguration()
49
+ {
50
+ let poolConfiguration = Mysql2ConnectionConfig.sanitize(this.config);
51
+ if(this.multipleStatements){
52
+ poolConfiguration.multipleStatements = true;
53
+ }
54
+ return poolConfiguration;
55
+ }
56
+
57
+ async disconnect()
58
+ {
59
+ if(!this.db){
60
+ return false;
61
+ }
62
+ await this.db.destroy();
63
+ this.db = false;
64
+ this.initialized = false;
65
+ return true;
66
+ }
67
+
68
+ generateEntities()
69
+ {
70
+ if(!this.rawEntities){
71
+ Logger.warning('Empty raw entities array, none entities generated.');
72
+ return {};
73
+ }
74
+ this.entities = {};
75
+ for(let i of Object.keys(this.rawEntities)){
76
+ let rawEntity = this.rawEntities[i];
77
+ if(!sc.isString(sc.get(rawEntity, 'tableName', false))){
78
+ Logger.critical('Invalid raw entity "'+i+'".');
79
+ continue;
80
+ }
81
+ this.entities[i] = new KyselyDriver({
82
+ rawModel: rawEntity,
83
+ id: i,
84
+ name: i,
85
+ config: this.config,
86
+ server: this,
87
+ db: this.db,
88
+ sql: this.kyselyModules.sql
89
+ });
90
+ }
91
+ this.entityManager.setEntities(this.entities);
92
+ return this.entities;
93
+ }
94
+
95
+ name()
96
+ {
97
+ return this.name || 'Kysely Data Server Driver';
98
+ }
99
+
100
+ async rawQuery(content)
101
+ {
102
+ let result = await this.kyselyModules.sql.raw(content).execute(this.db);
103
+ if(!sc.hasOwn(result, 'numAffectedRows')){
104
+ return result.rows;
105
+ }
106
+ return {
107
+ affectedRows: Number(sc.get(result, 'numAffectedRows', 0)),
108
+ insertId: Number(sc.get(result, 'insertId', 0))
109
+ };
110
+ }
111
+
112
+ async fetchEntitiesFromDatabase()
113
+ {
114
+ if(!this.initialized){
115
+ Logger.critical('Connection was not initialized, please use the connect method first.');
116
+ return false;
117
+ }
118
+ try {
119
+ return await MySQLTablesProvider.fetchTables(this);
120
+ } catch(error) {
121
+ Logger.critical('Kysely Data Server tables fetch failed. '+error.message);
122
+ return false;
123
+ }
124
+ }
125
+
126
+ }
127
+
128
+ module.exports.KyselyDataServer = KyselyDataServer;