@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.
- package/README.md +113 -23
- package/bin/generate-prisma-schema.js +88 -0
- package/bin/reldens-storage.js +75 -0
- package/index.js +27 -6
- package/lib/base-data-server.js +5 -0
- package/lib/entities-generator.js +605 -0
- package/lib/entity-properties.js +26 -0
- package/lib/entity-templates/entities-config.template +13 -0
- package/lib/entity-templates/entities-translations.template +11 -0
- package/lib/entity-templates/entity.template +32 -0
- package/lib/entity-templates/mikro-orm-model.template +37 -0
- package/lib/entity-templates/objection-js-model.template +19 -0
- package/lib/entity-templates/prisma-model.template +32 -0
- package/lib/entity-templates/registered-models.template +19 -0
- package/lib/mikro-orm/mikro-orm-data-server.js +42 -5
- package/lib/mikro-orm/mikro-orm-driver.js +1 -1
- package/lib/mysql-tables-provider.js +87 -0
- package/lib/objection-js/objection-js-data-server.js +12 -1
- package/lib/prisma/prisma-data-server.js +114 -0
- package/lib/prisma/prisma-driver.js +523 -0
- package/lib/prisma/prisma-schema-generator.js +71 -0
- package/lib/type-mapper.js +86 -0
- package/package.json +14 -7
|
@@ -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,
|
|
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
|
-
|
|
89
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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;
|