@reldens/storage 0.32.0 → 0.34.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.
@@ -0,0 +1,37 @@
1
+ /**
2
+ *
3
+ * Reldens - {{modelClassName}}
4
+ *
5
+ */
6
+
7
+ const { MikroOrmCore } = require('@reldens/storage');
8
+ const { EntitySchema } = MikroOrmCore;
9
+
10
+ class {{modelClassName}}
11
+ {
12
+
13
+ constructor({{modelPropertiesList}})
14
+ {
15
+ {{modelPropertiesConstructor}}
16
+ }
17
+
18
+ static createByProps(props)
19
+ {
20
+ const {{{modelPropertiesList}}} = props;
21
+ return new this({{modelPropertiesList}});
22
+ }
23
+ {{modelRelations}}
24
+ }
25
+
26
+ const schema = new EntitySchema({
27
+ class: {{modelClassName}},
28
+ properties: {
29
+ {{entityPropertiesDefinition}}
30
+ },
31
+ });
32
+
33
+ module.exports = {
34
+ {{modelClassName}},
35
+ entity: {{modelClassName}},
36
+ schema: schema
37
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ *
3
+ * Reldens - {{modelClassName}}
4
+ *
5
+ */
6
+
7
+ const { ObjectionJsRawModel } = require('@reldens/storage');
8
+
9
+ class {{modelClassName}} extends ObjectionJsRawModel
10
+ {
11
+
12
+ static get tableName()
13
+ {
14
+ return '{{tableName}}';
15
+ }
16
+ {{modelRelations}}
17
+ }
18
+
19
+ module.exports.{{modelClassName}} = {{modelClassName}};
@@ -0,0 +1,32 @@
1
+ /**
2
+ *
3
+ * Reldens - {{modelClassName}}
4
+ *
5
+ */
6
+
7
+ const { PrismaClient } = require('@prisma/client');
8
+
9
+ class {{modelClassName}}
10
+ {
11
+
12
+ constructor({{modelPropertiesList}})
13
+ {
14
+ {{modelPropertiesConstructor}}
15
+ }
16
+
17
+ static get client()
18
+ {
19
+ if(!this._client){
20
+ this._client = new PrismaClient();
21
+ }
22
+ return this._client;
23
+ }
24
+
25
+ static get model()
26
+ {
27
+ return this.client['{{tableName}}'];
28
+ }
29
+ {{modelRelations}}
30
+ }
31
+
32
+ module.exports.{{modelClassName}} = {{modelClassName}};
@@ -0,0 +1,19 @@
1
+ /**
2
+ *
3
+ * Reldens - Registered Models
4
+ *
5
+ */
6
+
7
+ {{registeredModels}}
8
+ const { entitiesConfig } = require('../../entities-config');
9
+ const { entitiesTranslations } = require('../../entities-translations');
10
+
11
+ let rawRegisteredEntities = {
12
+ {{registeredEntitiesObject}}
13
+ };
14
+
15
+ module.exports.rawRegisteredEntities = rawRegisteredEntities;
16
+
17
+ module.exports.entitiesConfig = entitiesConfig;
18
+
19
+ module.exports.entitiesTranslations = entitiesTranslations;
@@ -6,10 +6,11 @@
6
6
 
7
7
  const { MikroOrmDriver } = require('./mikro-orm-driver');
8
8
  const { BaseDataServer } = require('../base-data-server');
9
+ const { MySQLTablesProvider } = require('../mysql-tables-provider');
9
10
  const { MikroORM } = require('@mikro-orm/core');
10
11
  const { MySqlDriver } = require('@mikro-orm/mysql');
11
12
  const { MongoDriver } = require('@mikro-orm/mongodb');
12
- const { Logger, ErrorManager } = require('@reldens/utils');
13
+ const { ErrorManager, Logger, sc } = require('@reldens/utils');
13
14
 
14
15
  class MikroOrmDataServer extends BaseDataServer
15
16
  {
@@ -22,9 +23,9 @@ class MikroOrmDataServer extends BaseDataServer
22
23
 
23
24
  constructor(props)
24
25
  {
25
- // @TODO - BETA - Finish implementation.
26
26
  super(props);
27
27
  this.entitiesPath = props.entitiesPath;
28
+ this.warnWhenNoEntities = Boolean(props.warnWhenNoEntities);
28
29
  }
29
30
 
30
31
  async connect()
@@ -36,7 +37,7 @@ class MikroOrmDataServer extends BaseDataServer
36
37
  driver: this.clientsMapped[(this.client || 'mongodb')],
37
38
  dbName: this.config.database,
38
39
  clientUrl: this.connectString,
39
- allowGlobalContext: true
40
+ allowGlobalContext: true,
40
41
  };
41
42
  if(this.rawEntities){
42
43
  providedSetup.entities = Object.values(this.rawEntities);
@@ -47,6 +48,7 @@ class MikroOrmDataServer extends BaseDataServer
47
48
  if(this.entitiesPath){
48
49
  providedSetup.entities = this.entitiesPath;
49
50
  }
51
+ providedSetup.discovery = {warnWhenNoEntities: this.warnWhenNoEntities};
50
52
  this.orm = await MikroORM.init(providedSetup);
51
53
  this.initialized = Date.now();
52
54
  return this.initialized;
@@ -85,8 +87,43 @@ class MikroOrmDataServer extends BaseDataServer
85
87
 
86
88
  async rawQuery(content)
87
89
  {
88
- // @TODO - BETA - Implement.
89
- ErrorManager.error('MikroORM rawQuery() not implemented.');
90
+ try {
91
+ let queryResult = await this.orm.em.execute(content);
92
+ if(!sc.isArray(queryResult) || 0 === queryResult.length){
93
+ return false;
94
+ }
95
+ return queryResult;
96
+ } catch(error) {
97
+ Logger.error('Raw query failed: '+error.message);
98
+ return false;
99
+ }
100
+ }
101
+
102
+ async fetchEntitiesFromDatabase()
103
+ {
104
+ if(!this.initialized){
105
+ Logger.error('Connection was not initialized, please use the connect method first.');
106
+ return false;
107
+ }
108
+ try {
109
+ if('mysql' === this.client){
110
+ return await MySQLTablesProvider.fetchTables(this);
111
+ }
112
+ if('mongodb' === this.client){
113
+ let tables = {};
114
+ let collections = await this.orm.em.getDriver().getConnection().db().listCollections().toArray();
115
+ for(let collection of collections){
116
+ tables[collection.name] = {
117
+ name: collection.name,
118
+ columns: {}
119
+ };
120
+ }
121
+ return tables;
122
+ }
123
+ ErrorManager.error('Unsupported client type: '+this.client);
124
+ } catch(error) {
125
+ ErrorManager.error('Failed to fetch tables from database: ' + error.message);
126
+ }
90
127
  }
91
128
 
92
129
  }
@@ -123,7 +123,7 @@ class MikroOrmDriver extends BaseDriver
123
123
  if (!entries){
124
124
  return false;
125
125
  }
126
- for(let entry of Object.keys(entries)){
126
+ for(let entry of entries){
127
127
  await this.repository.nativeDelete(entry.id);
128
128
  }
129
129
  }
@@ -0,0 +1,87 @@
1
+ /**
2
+ *
3
+ * Reldens - MySQLTablesProvider
4
+ *
5
+ */
6
+
7
+ const { ErrorManager, sc } = require('@reldens/utils');
8
+
9
+ class MySQLTablesProvider
10
+ {
11
+
12
+ static async fetchTables(server)
13
+ {
14
+ let tablesQuery =
15
+ 'SELECT ' +
16
+ ' TABLE_NAME, ' +
17
+ ' COLUMN_NAME, ' +
18
+ ' DATA_TYPE, ' +
19
+ ' CHARACTER_MAXIMUM_LENGTH, ' +
20
+ ' COLUMN_TYPE, ' +
21
+ ' IS_NULLABLE, ' +
22
+ ' COLUMN_KEY, ' +
23
+ ' EXTRA, ' +
24
+ ' COLUMN_DEFAULT ' +
25
+ 'FROM ' +
26
+ ' information_schema.COLUMNS ' +
27
+ 'WHERE ' +
28
+ ' TABLE_SCHEMA = \'' + server.config.database + '\' ' +
29
+ 'ORDER BY ' +
30
+ ' TABLE_NAME, ORDINAL_POSITION';
31
+ try {
32
+ let result = await server.rawQuery(tablesQuery);
33
+ if(!sc.isArray(result) || 0 === result.length){
34
+ ErrorManager.error('No tables found in the database.');
35
+ }
36
+ let tables = {};
37
+ for(let row of result){
38
+ if(!tables[row.TABLE_NAME]){
39
+ tables[row.TABLE_NAME] = {
40
+ name: row.TABLE_NAME,
41
+ columns: {}
42
+ };
43
+ }
44
+ tables[row.TABLE_NAME].columns[row.COLUMN_NAME] = {
45
+ name: row.COLUMN_NAME,
46
+ type: row.DATA_TYPE,
47
+ columnType: row.COLUMN_TYPE,
48
+ length: row.CHARACTER_MAXIMUM_LENGTH,
49
+ nullable: 'YES' === row.IS_NULLABLE,
50
+ key: row.COLUMN_KEY,
51
+ extra: row.EXTRA,
52
+ default: row.COLUMN_DEFAULT
53
+ };
54
+ }
55
+ let foreignKeysQuery =
56
+ 'SELECT ' +
57
+ ' TABLE_NAME, ' +
58
+ ' COLUMN_NAME, ' +
59
+ ' REFERENCED_TABLE_NAME, ' +
60
+ ' REFERENCED_COLUMN_NAME ' +
61
+ 'FROM ' +
62
+ ' information_schema.KEY_COLUMN_USAGE ' +
63
+ 'WHERE ' +
64
+ ' TABLE_SCHEMA = \'' + server.config.database + '\' ' +
65
+ ' AND REFERENCED_TABLE_NAME IS NOT NULL';
66
+
67
+ let foreignKeysResult = await server.rawQuery(foreignKeysQuery);
68
+ if(sc.isArray(foreignKeysResult) && 0 < foreignKeysResult.length){
69
+ for(let row of foreignKeysResult){
70
+ if(
71
+ tables[row.TABLE_NAME] &&
72
+ tables[row.TABLE_NAME].columns[row.COLUMN_NAME]
73
+ ){
74
+ tables[row.TABLE_NAME].columns[row.COLUMN_NAME].referencedTable = row.REFERENCED_TABLE_NAME;
75
+ tables[row.TABLE_NAME].columns[row.COLUMN_NAME].referencedColumn = row.REFERENCED_COLUMN_NAME;
76
+ }
77
+ }
78
+ }
79
+ return tables;
80
+ } catch(error) {
81
+ ErrorManager.error('Failed to fetch tables from database: '+error.message);
82
+ }
83
+ }
84
+
85
+ }
86
+
87
+ module.exports.MySQLTablesProvider = MySQLTablesProvider;
@@ -6,6 +6,7 @@
6
6
 
7
7
  const { BaseDataServer } = require('../base-data-server');
8
8
  const { ObjectionJsDriver } = require('./objection-js-driver');
9
+ const { MySQLTablesProvider } = require('../mysql-tables-provider');
9
10
  const { Model } = require('objection');
10
11
  const Knex = require('knex');
11
12
  const { Logger } = require('@reldens/utils');
@@ -72,7 +73,17 @@ class ObjectionJsDataServer extends BaseDataServer
72
73
 
73
74
  async rawQuery(content)
74
75
  {
75
- return await this.knex.raw(content);
76
+ let result = await this.knex.raw(content);
77
+ return result[0] || false;
78
+ }
79
+
80
+ async fetchEntitiesFromDatabase()
81
+ {
82
+ if(!this.initialized){
83
+ Logger.error('Connection was not initialized, please use the connect method first.');
84
+ return false;
85
+ }
86
+ return await MySQLTablesProvider.fetchTables(this);
76
87
  }
77
88
 
78
89
  }
@@ -0,0 +1,114 @@
1
+ /**
2
+ *
3
+ * Reldens - PrismaDataServer
4
+ *
5
+ */
6
+
7
+ const { BaseDataServer } = require('../base-data-server');
8
+ const { PrismaDriver } = require('./prisma-driver');
9
+ const { MySQLTablesProvider } = require('../mysql-tables-provider');
10
+ const { ErrorManager, Logger, sc } = require('@reldens/utils');
11
+
12
+ class PrismaDataServer extends BaseDataServer
13
+ {
14
+
15
+ constructor(props)
16
+ {
17
+ super(props);
18
+ this.prisma = false;
19
+ }
20
+
21
+ async connect()
22
+ {
23
+ if(this.initialized){
24
+ return this.initialized;
25
+ }
26
+ try {
27
+ let { PrismaClient } = require('@prisma/client');
28
+ this.prisma = new PrismaClient({
29
+ log: this.debug ? ['query', 'info', 'warn', 'error'] : ['error']
30
+ });
31
+ await this.prisma.$connect();
32
+ this.initialized = Date.now();
33
+ return this.initialized;
34
+ } catch(error) {
35
+ Logger.critical('Connection failed, Prisma error: '+error.message);
36
+ }
37
+ return false;
38
+ }
39
+
40
+ generateEntities()
41
+ {
42
+ if(!this.initialized){
43
+ Logger.warning('Connection was not initialized, please use the connect method first.');
44
+ return {};
45
+ }
46
+ if(!this.rawEntities){
47
+ Logger.warning('Empty raw entities array, none entities generated.');
48
+ return {};
49
+ }
50
+ this.entities = {};
51
+ for(let i of Object.keys(this.rawEntities)){
52
+ let rawEntity = this.rawEntities[i];
53
+ let modelName = i.toLowerCase();
54
+ if(!this.prisma[modelName]){
55
+ Logger.critical('Invalid raw entity "'+i+'". No matching Prisma model found.');
56
+ continue;
57
+ }
58
+ this.entities[i] = new PrismaDriver({
59
+ rawModel: rawEntity,
60
+ id: i,
61
+ name: i,
62
+ config: this.config,
63
+ prisma: this.prisma,
64
+ model: this.prisma[modelName],
65
+ server: this
66
+ });
67
+ }
68
+ this.entityManager.setEntities(this.entities);
69
+ return this.entities;
70
+ }
71
+
72
+ name()
73
+ {
74
+ return this.name || 'Prisma Data Server Driver';
75
+ }
76
+
77
+ async rawQuery(content)
78
+ {
79
+ try {
80
+ let queryResult = await this.prisma.$queryRawUnsafe(content);
81
+ if(!sc.isArray(queryResult) || 0 === queryResult.length){
82
+ return false;
83
+ }
84
+ return queryResult;
85
+ } catch(error) {
86
+ Logger.error('Raw query failed: '+error.message);
87
+ return false;
88
+ }
89
+ }
90
+
91
+ async fetchEntitiesFromDatabase()
92
+ {
93
+ if(!this.initialized){
94
+ Logger.error('Connection was not initialized, please use the connect method first.');
95
+ return false;
96
+ }
97
+ try {
98
+ return await MySQLTablesProvider.fetchTables(this);
99
+ } catch(error) {
100
+ ErrorManager.error('Failed to fetch tables from database: '+error.message);
101
+ }
102
+ }
103
+
104
+ async disconnect()
105
+ {
106
+ if(this.prisma){
107
+ await this.prisma.$disconnect();
108
+ }
109
+ this.initialized = false;
110
+ }
111
+
112
+ }
113
+
114
+ module.exports.PrismaDataServer = PrismaDataServer;