@reldens/storage 0.55.0 → 0.57.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.
@@ -48,10 +48,12 @@ class EntitiesGenerator
48
48
  this.server = sc.get(props, 'server', false);
49
49
  this.connectionData = sc.get(props, 'connectionData', false);
50
50
  this.isOverride = sc.get(props, 'isOverride', false);
51
+ this.prismaClient = sc.get(props, 'prismaClient', false);
51
52
  this.generatedEntities = {};
52
53
  this.existingEntities = {};
53
54
  this.existingEntityFields = {};
54
55
  this.existingModels = {};
56
+ this.prismaRelationsMetadata = {};
55
57
  this.entitiesGeneration = new EntitiesGeneration({
56
58
  entitiesFolder: this.entitiesFolder,
57
59
  templatePath: this.templates['entity']
@@ -163,6 +165,125 @@ class EntitiesGenerator
163
165
  return false;
164
166
  }
165
167
 
168
+ extractPrismaRelationsMetadata()
169
+ {
170
+ if(!this.prismaClient){
171
+ Logger.warning('Missing PrismaClient.');
172
+ return;
173
+ }
174
+ if(!this.server || !(this.server instanceof PrismaDataServer)){
175
+ Logger.warning('Server is not a PrismaDataServer instance.');
176
+ return;
177
+ }
178
+ try {
179
+ let dmmf = this.prismaClient._runtimeDataModel || this.prismaClient._dmmf?.datamodel;
180
+ if(!dmmf || !dmmf.models){
181
+ Logger.warning('Could not extract Prisma DMMF data for relations metadata.');
182
+ return;
183
+ }
184
+ if(sc.isArray(dmmf.models)){
185
+ this.processArrayModels(dmmf.models);
186
+ return;
187
+ }
188
+ this.processObjectModels(dmmf.models);
189
+ } catch(error) {
190
+ Logger.warning('Failed to extract Prisma relations metadata: ' + error.message);
191
+ }
192
+ }
193
+
194
+ processArrayModels(models)
195
+ {
196
+ for(let model of models){
197
+ if(!model){
198
+ Logger.error('Missing model.');
199
+ continue;
200
+ }
201
+ if(!model.name){
202
+ Logger.error('Missing model name.', model);
203
+ continue;
204
+ }
205
+ if(!sc.isArray(model.fields)){
206
+ Logger.error('Model fields not an array.', model);
207
+ continue;
208
+ }
209
+ this.processModelForRelations(model.name, model, models);
210
+ }
211
+ Logger.info('Extracted relations metadata for ' + Object.keys(this.prismaRelationsMetadata).length + ' models.');
212
+ }
213
+
214
+ processObjectModels(models)
215
+ {
216
+ for(let modelName of Object.keys(models)){
217
+ let model = models[modelName];
218
+ if(!model){
219
+ Logger.error('Missing model.');
220
+ continue;
221
+ }
222
+ if(!sc.isArray(model.fields)){
223
+ Logger.error('Model fields not an array.', model);
224
+ continue;
225
+ }
226
+ this.processModelForRelations(modelName, model, models);
227
+ }
228
+ Logger.info('Extracted relations metadata for ' + Object.keys(this.prismaRelationsMetadata).length + ' models.');
229
+ }
230
+
231
+ processModelForRelations(modelName, model, allModels)
232
+ {
233
+ let tableName = modelName.toLowerCase();
234
+ this.prismaRelationsMetadata[tableName] = {};
235
+ for(let field of model.fields){
236
+ if('object' !== field.kind){
237
+ continue;
238
+ }
239
+ let relationType = 'many';
240
+ if(!field.isList){
241
+ relationType = this.inferRelationType(field, model, allModels, modelName);
242
+ }
243
+ this.prismaRelationsMetadata[tableName][field.name] = {
244
+ type: relationType,
245
+ model: field.type,
246
+ isList: field.isList,
247
+ isOptional: field.isOptional,
248
+ relationName: field.relationName
249
+ };
250
+ }
251
+ }
252
+
253
+ inferRelationType(field, model, allModels, modelName)
254
+ {
255
+ if(field.isList){
256
+ return 'many';
257
+ }
258
+ let relatedModel = this.findRelatedModel(allModels, field.type);
259
+ if(!relatedModel){
260
+ return 'one';
261
+ }
262
+ let backReference = relatedModel.fields.find(f =>
263
+ 'object' === f.kind &&
264
+ f.type === modelName &&
265
+ f.relationName === field.relationName
266
+ );
267
+ if(!backReference){
268
+ return 'one';
269
+ }
270
+ if(field.relationFromFields && 0 < field.relationFromFields.length){
271
+ return 'one';
272
+ }
273
+ if(backReference.relationFromFields && 0 < backReference.relationFromFields.length){
274
+ return 'one';
275
+ }
276
+ return 'one';
277
+ }
278
+
279
+ findRelatedModel(allModels, fieldType)
280
+ {
281
+ if(sc.isArray(allModels)){
282
+ return allModels.find(m => m.name === fieldType);
283
+ }
284
+ return allModels[fieldType];
285
+ }
286
+
166
287
  filterTablesToGenerate(tables, driverKey)
167
288
  {
168
289
  let filteredTables = {};
@@ -253,6 +374,18 @@ class EntitiesGenerator
253
374
  Logger.critical('Failed to connect to database: '+error.message);
254
375
  return false;
255
376
  }
377
+ let driverKey = sc.get(
378
+ this.connectionData,
379
+ 'driver',
380
+ (this.server ? sc.get(this.driversClassMap, this.server.constructor.name, false) : false)
381
+ );
382
+ if('prisma' === driverKey){
383
+ if(!this.prismaClient && this.server.prisma){
384
+ this.prismaClient = this.server.prisma;
385
+ }
386
+ Logger.debug('Extract Prisma relations metadata.');
387
+ this.extractPrismaRelationsMetadata();
388
+ }
256
389
  let tables = await this.server.fetchEntitiesFromDatabase();
257
390
  if(!tables){
258
391
  Logger.critical('EntitiesGenerator tables fetch failed.');
@@ -263,15 +396,13 @@ class EntitiesGenerator
263
396
  }
264
397
  this.detectExistingEntities();
265
398
  this.detectExistingModels();
266
- let driverKey = sc.get(
267
- this.connectionData,
268
- 'driver',
269
- (this.server ? sc.get(this.driversClassMap, this.server.constructor.name, false) : false)
270
- );
271
399
  if(!driverKey){
272
400
  Logger.critical('Failed to fetch driver key.');
273
401
  return false;
274
402
  }
403
+ if('objection-js' === driverKey){
404
+ this.modelsGeneration.setAllTablesData(tables);
405
+ }
275
406
  let tablesToGenerate = this.filterTablesToGenerate(tables, driverKey);
276
407
  if(0 === Object.keys(tablesToGenerate).length && !this.isOverride){
277
408
  return true;
@@ -283,11 +414,13 @@ class EntitiesGenerator
283
414
  continue;
284
415
  }
285
416
  let entityInfo = this.entitiesGeneration.generatedEntities[tableName];
417
+ let relationMetadata = sc.get(this.prismaRelationsMetadata, tableName, {});
286
418
  let modelGenerated = await this.modelsGeneration.generateModelFile(
287
419
  tableName,
288
420
  tableData,
289
421
  driverKey,
290
- entityInfo
422
+ entityInfo,
423
+ relationMetadata
291
424
  );
292
425
  if(modelGenerated){
293
426
  let modelInfo = this.modelsGeneration.generatedModels[tableName];
@@ -327,7 +460,7 @@ class EntitiesGenerator
327
460
  Logger.critical('Unsupported driver: '+driverKey);
328
461
  return false;
329
462
  }
330
- this.server = new driverClassMapped({
463
+ let serverConfig = {
331
464
  client: sc.get(this.connectionData, 'client', 'mysql2'),
332
465
  config: {
333
466
  user: sc.get(this.connectionData, 'user', ''),
@@ -336,7 +469,11 @@ class EntitiesGenerator
336
469
  host: sc.get(this.connectionData, 'host', 'localhost'),
337
470
  port: sc.get(this.connectionData, 'port', 3306)
338
471
  }
339
- });
472
+ };
473
+ if('prisma' === driverKey && this.prismaClient){
474
+ serverConfig.prismaClient = this.prismaClient;
475
+ }
476
+ this.server = new driverClassMapped(serverConfig);
340
477
  return this.server;
341
478
  }
342
479
 
@@ -4,8 +4,6 @@
4
4
  *
5
5
  */
6
6
 
7
- const { PrismaClient } = require('@prisma/client');
8
-
9
7
  class {{modelClassName}}
10
8
  {
11
9
 
@@ -14,19 +12,6 @@ class {{modelClassName}}
14
12
  {{modelPropertiesConstructor}}
15
13
  }
16
14
 
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
-
30
15
  static get tableName()
31
16
  {
32
17
  return '{{tableName}}';
@@ -18,9 +18,10 @@ class ModelsGeneration extends BaseGenerator
18
18
  this.modelsFolder = sc.get(props, 'modelsFolder', '');
19
19
  this.templates = sc.get(props, 'templates', {});
20
20
  this.generatedModels = {};
21
+ this.allTablesData = {};
21
22
  }
22
23
 
23
- async generateModelFile(tableName, tableData, driverKey, entityInfo)
24
+ async generateModelFile(tableName, tableData, driverKey, entityInfo, relationMetadata = {})
24
25
  {
25
26
  let modelTemplatePath = this.templates[driverKey];
26
27
  if(!FileHandler.exists(modelTemplatePath)){
@@ -37,7 +38,7 @@ class ModelsGeneration extends BaseGenerator
37
38
  let modelPropertiesConstructor = Object.keys(tableData.columns)
38
39
  .map(columnName => 'this.'+columnName+' = '+columnName+';')
39
40
  .join('\n ');
40
- let modelRelations = '';
41
+ let modelRelations = this.generateModelRelations(tableName, tableData, relationMetadata, driverKey);
41
42
  let entityPropertiesDefinition = this.getEntityPropertiesDefinition(tableData.columns, driverKey);
42
43
  let replacements = {
43
44
  modelClassName,
@@ -65,6 +66,147 @@ class ModelsGeneration extends BaseGenerator
65
66
  return true;
66
67
  }
67
68
 
69
+ setAllTablesData(allTablesData)
70
+ {
71
+ this.allTablesData = allTablesData;
72
+ }
73
+
74
+ generateModelRelations(tableName, tableData, relationMetadata, driverKey)
75
+ {
76
+ if('prisma' === driverKey){
77
+ return this.generatePrismaRelations(relationMetadata);
78
+ }
79
+ if('objection-js' === driverKey){
80
+ return this.generateObjectionJsRelations(tableName, tableData);
81
+ }
82
+ return '';
83
+ }
84
+
85
+ generatePrismaRelations(relationMetadata)
86
+ {
87
+ if(!relationMetadata || 0 === Object.keys(relationMetadata).length){
88
+ return '';
89
+ }
90
+ let relationTypesArray = [];
91
+ for(let relationName of Object.keys(relationMetadata)){
92
+ let relation = relationMetadata[relationName];
93
+ relationTypesArray.push(' '+relationName+': \''+relation.type+'\'');
94
+ }
95
+ if(0 === relationTypesArray.length){
96
+ return '';
97
+ }
98
+ return '\n\n static get relationTypes()\n {\n return {\n '+relationTypesArray.join(',\n ')+'\n };\n }';
99
+ }
100
+
101
+ generateObjectionJsRelations(tableName, tableData)
102
+ {
103
+ let relations = this.detectObjectionJsRelations(tableName, tableData);
104
+ let reverseRelations = this.detectReverseObjectionJsRelations(tableName);
105
+ let allRelations = Object.assign({}, relations, reverseRelations);
106
+ if(0 === Object.keys(allRelations).length){
107
+ return '';
108
+ }
109
+ let relationMappings = [];
110
+ let requiredModels = [];
111
+ for(let relationKey of Object.keys(allRelations)){
112
+ let relation = allRelations[relationKey];
113
+ let tableReference = relation.referencedTable || relation.referencingTable;
114
+ let relatedModelClass = sc.capitalizedCamelCase(tableReference)+'Model';
115
+ if(!requiredModels.find(m => m.modelClass === relatedModelClass)){
116
+ requiredModels.push({
117
+ modelClass: relatedModelClass,
118
+ fileName: sc.kebabCase(tableReference)+'-model'
119
+ });
120
+ }
121
+ let relationMapping = ' '+relationKey+': {\n';
122
+ relationMapping += ' relation: this.'+relation.relationType+',\n';
123
+ relationMapping += ' modelClass: '+relatedModelClass+',\n';
124
+ relationMapping += ' join: {\n';
125
+ relationMapping += ' from: this.tableName+\'.'+relation.fromColumn+'\',\n';
126
+ relationMapping += ' to: '+relatedModelClass+'.tableName+\'.'+relation.toColumn+'\'\n';
127
+ relationMapping += ' }\n';
128
+ relationMapping += ' }';
129
+ relationMappings.push(relationMapping);
130
+ }
131
+ if(0 === relationMappings.length){
132
+ return '';
133
+ }
134
+ let requireStatements = [];
135
+ for(let modelInfo of requiredModels){
136
+ requireStatements.push(' const { '+modelInfo.modelClass+' } = require(\'./'+modelInfo.fileName+'\');');
137
+ }
138
+ let relationMappingsMethod = '\n\n static get relationMappings()\n {\n';
139
+ relationMappingsMethod += requireStatements.join('\n')+'\n';
140
+ relationMappingsMethod += ' return {\n';
141
+ relationMappingsMethod += relationMappings.join(',\n');
142
+ relationMappingsMethod += '\n };\n';
143
+ relationMappingsMethod += ' }';
144
+ return relationMappingsMethod;
145
+ }
146
+
147
+ detectObjectionJsRelations(tableName, tableData)
148
+ {
149
+ let relations = {};
150
+ for(let columnName of Object.keys(tableData.columns)){
151
+ let column = tableData.columns[columnName];
152
+ if(!sc.hasOwn(column, 'referencedTable')){
153
+ continue;
154
+ }
155
+ let relationKey = 'related_'+column.referencedTable;
156
+ let relationType = this.determineRelationType(column, true);
157
+ relations[relationKey] = {
158
+ fromColumn: columnName,
159
+ toColumn: column.referencedColumn,
160
+ referencedTable: column.referencedTable,
161
+ relationType: relationType
162
+ };
163
+ }
164
+ return relations;
165
+ }
166
+
167
+ detectReverseObjectionJsRelations(tableName)
168
+ {
169
+ let reverseRelations = {};
170
+ for(let otherTableName of Object.keys(this.allTablesData)){
171
+ if(otherTableName === tableName){
172
+ continue;
173
+ }
174
+ let otherTableData = this.allTablesData[otherTableName];
175
+ for(let columnName of Object.keys(otherTableData.columns)){
176
+ let column = otherTableData.columns[columnName];
177
+ if(!sc.hasOwn(column, 'referencedTable')){
178
+ continue;
179
+ }
180
+ if(column.referencedTable !== tableName){
181
+ continue;
182
+ }
183
+ let relationKey = 'related_'+otherTableName;
184
+ let relationType = this.determineRelationType(column, false);
185
+ reverseRelations[relationKey] = {
186
+ fromColumn: column.referencedColumn,
187
+ toColumn: columnName,
188
+ referencingTable: otherTableName,
189
+ relationType: relationType
190
+ };
191
+ }
192
+ }
193
+ return reverseRelations;
194
+ }
195
+
196
+ determineRelationType(column, isForwardRelation)
197
+ {
198
+ if(isForwardRelation){
199
+ if('PRI' === column.key){
200
+ return 'HasOneRelation';
201
+ }
202
+ return 'BelongsToOneRelation';
203
+ }
204
+ if('PRI' === column.key){
205
+ return 'HasOneRelation';
206
+ }
207
+ return 'HasManyRelation';
208
+ }
209
+
68
210
  getEntityPropertiesDefinition(columns, driverKey)
69
211
  {
70
212
  if('mikro-orm' === driverKey){
@@ -15,7 +15,7 @@ class MySQLTablesProvider
15
15
  ' TABLE_NAME, ' +
16
16
  ' COLUMN_NAME, ' +
17
17
  ' DATA_TYPE, ' +
18
- ' CHARACTER_MAXIMUM_LENGTH, ' +
18
+ ' CAST(CHARACTER_MAXIMUM_LENGTH AS CHAR) as CHARACTER_MAXIMUM_LENGTH, ' +
19
19
  ' COLUMN_TYPE, ' +
20
20
  ' IS_NULLABLE, ' +
21
21
  ' COLUMN_KEY, ' +
@@ -8,7 +8,7 @@ const { BaseDataServer } = require('../base-data-server');
8
8
  const { PrismaDriver } = require('./prisma-driver');
9
9
  const { MySQLTablesProvider } = require('../mysql-tables-provider');
10
10
  const { PrismaClient } = require('@prisma/client');
11
- const { Logger } = require('@reldens/utils');
11
+ const { Logger, sc } = require('@reldens/utils');
12
12
 
13
13
  class PrismaDataServer extends BaseDataServer
14
14
  {
@@ -16,7 +16,7 @@ class PrismaDataServer extends BaseDataServer
16
16
  constructor(props)
17
17
  {
18
18
  super(props);
19
- this.prisma = false;
19
+ this.prisma = sc.get(props, 'prismaClient', false);
20
20
  }
21
21
 
22
22
  async connect()
@@ -25,10 +25,15 @@ class PrismaDataServer extends BaseDataServer
25
25
  return this.initialized;
26
26
  }
27
27
  try {
28
- this.prisma = new PrismaClient({
29
- log: this.debug ? ['query', 'info', 'warn', 'error'] : ['error']
30
- });
28
+ if(!this.prisma){
29
+ this.prisma = new PrismaClient({
30
+ datasources: {db: {url: this.connectString}},
31
+ log: this.debug ? ['query', 'info', 'warn', 'error'] : ['error']
32
+ });
33
+ }
31
34
  await this.prisma.$connect();
35
+ let dbTest = await this.prisma.$queryRaw`SELECT DATABASE() as current_db`;
36
+ Logger.info('Connected to database: ' + dbTest[0].current_db);
32
37
  this.initialized = Date.now();
33
38
  return this.initialized;
34
39
  } catch(error) {
@@ -86,14 +91,16 @@ class PrismaDataServer extends BaseDataServer
86
91
  continue;
87
92
  }
88
93
  try {
89
- results.push(await this.executeStatement(cleanStatement));
94
+ let result = await this.executeStatement(cleanStatement);
95
+ results.push(result);
96
+ //Logger.debug('Statement executed, result: ' + JSON.stringify(result));
90
97
  } catch(stmtError) {
91
98
  Logger.error('Statement "'+cleanStatement+'" execution failed: '+stmtError.message);
92
99
  return false;
93
100
  }
94
101
  }
95
102
  if(0 === results.length){
96
- Logger.error('Statement results length is zero.', results);
103
+ //Logger.error('Statement results length is zero.', results);
97
104
  return false;
98
105
  }
99
106
  return 1 === results.length ? results[0] : results;
@@ -109,7 +116,11 @@ class PrismaDataServer extends BaseDataServer
109
116
  if(trimmedStatement.startsWith('SELECT')){
110
117
  return await this.prisma.$queryRawUnsafe(statement);
111
118
  }
119
+ if(trimmedStatement.startsWith('SHOW')){
120
+ return await this.prisma.$queryRawUnsafe(statement);
121
+ }
112
122
  let result = await this.prisma.$executeRawUnsafe(statement);
123
+ Logger.debug('Raw result from Prisma: ' + result);
113
124
  if(
114
125
  trimmedStatement.startsWith('CREATE')
115
126
  || trimmedStatement.startsWith('ALTER')
@@ -33,7 +33,9 @@ class PrismaDriver extends BaseDriver
33
33
  this.fieldTypes = {};
34
34
  this.idFieldType = 'String';
35
35
  this.referenceFields = {};
36
+ this.relationMetadata = {};
36
37
  this.initFieldMetadata();
38
+ this.initRelationMetadata();
37
39
  }
38
40
 
39
41
  initFieldMetadata()
@@ -69,6 +71,44 @@ class PrismaDriver extends BaseDriver
69
71
  }
70
72
  }
71
73
 
74
+ initRelationMetadata()
75
+ {
76
+ try {
77
+ let dmmf = this.prisma._runtimeDataModel || Prisma.dmmf?.datamodel;
78
+ if(!dmmf){
79
+ return;
80
+ }
81
+ let modelName = this.tableName().toLowerCase();
82
+ let modelInfo = dmmf.models?.[modelName] || dmmf.models?.find(m => m.name.toLowerCase() === modelName);
83
+ if(!modelInfo){
84
+ return;
85
+ }
86
+ for(let field of modelInfo.fields){
87
+ if('object' === field.kind){
88
+ let relationType = 'many';
89
+ if(!field.isList){
90
+ relationType = 'one';
91
+ }
92
+ this.relationMetadata[field.name] = {
93
+ type: relationType,
94
+ model: field.type,
95
+ isList: field.isList,
96
+ isOptional: field.isOptional
97
+ };
98
+ }
99
+ }
100
+ if(this.rawModel && this.rawModel.relationTypes){
101
+ for(let relationName of Object.keys(this.rawModel.relationTypes)){
102
+ if(sc.hasOwn(this.relationMetadata, relationName)){
103
+ this.relationMetadata[relationName].type = this.rawModel.relationTypes[relationName];
104
+ }
105
+ }
106
+ }
107
+ } catch(error) {
108
+ Logger.warning('Could not initialize relation metadata: '+error.message);
109
+ }
110
+ }
111
+
72
112
  castIdValue(id)
73
113
  {
74
114
  if(null === id || undefined === id){
@@ -239,6 +279,43 @@ class PrismaDriver extends BaseDriver
239
279
  return processedFilters;
240
280
  }
241
281
 
282
+ transformRelationResults(result, includeConfig)
283
+ {
284
+ if(!result || !includeConfig){
285
+ return result;
286
+ }
287
+ if(sc.isArray(result)){
288
+ return result.map(item => this.transformSingleResult(item, includeConfig));
289
+ }
290
+ return this.transformSingleResult(result, includeConfig);
291
+ }
292
+
293
+ transformSingleResult(item, includeConfig)
294
+ {
295
+ if(!item || !sc.isObject(item)){
296
+ return item;
297
+ }
298
+ let transformed = {...item};
299
+ for(let relationName of Object.keys(includeConfig)){
300
+ if(!sc.hasOwn(transformed, relationName)){
301
+ continue;
302
+ }
303
+ let relationMeta = this.relationMetadata[relationName];
304
+ if(!relationMeta){
305
+ continue;
306
+ }
307
+ let relationValue = transformed[relationName];
308
+ if('one' === relationMeta.type && sc.isArray(relationValue)){
309
+ transformed[relationName] = 0 < relationValue.length ? relationValue[0] : null;
310
+ continue;
311
+ }
312
+ if('many' === relationMeta.type && !sc.isArray(relationValue)){
313
+ transformed[relationName] = relationValue ? [relationValue] : [];
314
+ }
315
+ }
316
+ return transformed;
317
+ }
318
+
242
319
  async create(params)
243
320
  {
244
321
  try {
@@ -439,10 +516,13 @@ class PrismaDriver extends BaseDriver
439
516
  {
440
517
  try {
441
518
  let query = this.buildQueryOptions();
519
+ let includeConfig = {};
442
520
  if(sc.isArray(relations) && 0 < relations.length){
443
- query.include = this.buildIncludeObject(relations);
521
+ includeConfig = this.buildIncludeObject(relations);
522
+ query.include = includeConfig;
444
523
  }
445
- return await this.model.findMany(query);
524
+ let results = await this.model.findMany(query);
525
+ return this.transformRelationResults(results, includeConfig);
446
526
  } catch(error) {
447
527
  Logger.error('Load all with relations error: '+error.message);
448
528
  return [];
@@ -468,10 +548,13 @@ class PrismaDriver extends BaseDriver
468
548
  let processedFilters = this.processFilters(filters);
469
549
  let query = this.buildQueryOptions();
470
550
  query.where = processedFilters;
551
+ let includeConfig = {};
471
552
  if(sc.isArray(relations) && 0 < relations.length){
472
- query.include = this.buildIncludeObject(relations);
553
+ includeConfig = this.buildIncludeObject(relations);
554
+ query.include = includeConfig;
473
555
  }
474
- return await this.model.findMany(query);
556
+ let results = await this.model.findMany(query);
557
+ return this.transformRelationResults(results, includeConfig);
475
558
  } catch(error) {
476
559
  Logger.error('Load with relations error: '+error.message);
477
560
  return [];
@@ -497,10 +580,13 @@ class PrismaDriver extends BaseDriver
497
580
  let filter = this.createSingleFilter(field, fieldValue, operator);
498
581
  let query = this.buildQueryOptions();
499
582
  query.where = filter;
583
+ let includeConfig = {};
500
584
  if(sc.isArray(relations) && 0 < relations.length){
501
- query.include = this.buildIncludeObject(relations);
585
+ includeConfig = this.buildIncludeObject(relations);
586
+ query.include = includeConfig;
502
587
  }
503
- return await this.model.findMany(query);
588
+ let results = await this.model.findMany(query);
589
+ return this.transformRelationResults(results, includeConfig);
504
590
  } catch(error) {
505
591
  Logger.error('Load by with relations error: '+error.message);
506
592
  return [];
@@ -527,10 +613,13 @@ class PrismaDriver extends BaseDriver
527
613
  let query = {
528
614
  where: {id: castedId}
529
615
  };
616
+ let includeConfig = {};
530
617
  if(sc.isArray(relations) && 0 < relations.length){
531
- query.include = this.buildIncludeObject(relations);
618
+ includeConfig = this.buildIncludeObject(relations);
619
+ query.include = includeConfig;
532
620
  }
533
- return await this.model.findUnique(query);
621
+ let result = await this.model.findUnique(query);
622
+ return this.transformRelationResults(result, includeConfig);
534
623
  } catch(error) {
535
624
  Logger.error('Load by ID with relations error: '+error.message);
536
625
  return null;
@@ -571,10 +660,13 @@ class PrismaDriver extends BaseDriver
571
660
  let processedFilters = this.processFilters(filters);
572
661
  let query = this.buildQueryOptions(false);
573
662
  query.where = processedFilters;
663
+ let includeConfig = {};
574
664
  if(sc.isArray(relations) && 0 < relations.length){
575
- query.include = this.buildIncludeObject(relations);
665
+ includeConfig = this.buildIncludeObject(relations);
666
+ query.include = includeConfig;
576
667
  }
577
- return await this.model.findFirst(query);
668
+ let result = await this.model.findFirst(query);
669
+ return this.transformRelationResults(result, includeConfig);
578
670
  } catch(error) {
579
671
  Logger.error('Load one with relations error: '+error.message);
580
672
  return null;
@@ -600,10 +692,13 @@ class PrismaDriver extends BaseDriver
600
692
  let filter = this.createSingleFilter(field, fieldValue, operator);
601
693
  let query = this.buildQueryOptions(false);
602
694
  query.where = filter;
695
+ let includeConfig = {};
603
696
  if(sc.isArray(relations) && 0 < relations.length){
604
- query.include = this.buildIncludeObject(relations);
697
+ includeConfig = this.buildIncludeObject(relations);
698
+ query.include = includeConfig;
605
699
  }
606
- return await this.model.findFirst(query);
700
+ let result = await this.model.findFirst(query);
701
+ return this.transformRelationResults(result, includeConfig);
607
702
  } catch(error) {
608
703
  Logger.error('Load one by with relations error: '+error.message);
609
704
  return null;
@@ -62,19 +62,19 @@ class PrismaSchemaGenerator
62
62
  async waitForSchemaGeneration()
63
63
  {
64
64
  let clientPath = this.clientOutputPath || 'node_modules/.prisma/client';
65
- let generatedClientPath = clientPath.startsWith('node_modules')
66
- ? FileHandler.joinPaths(process.cwd(), clientPath)
67
- : FileHandler.joinPaths(this.prismaSchemaPath, clientPath);
65
+ let generatedClientPath = this.resolveClientPath(clientPath);
68
66
  let clientIndexPath = FileHandler.joinPaths(generatedClientPath, 'index.js');
69
67
  let startTime = Date.now();
70
68
  return new Promise((resolve) => {
71
69
  let interval = setInterval(() => {
70
+ let awaitTime = Date.now() - startTime;
71
+ Logger.info('Awaiting on schema generation: ' + clientIndexPath, (awaitTime/1000).toFixed(0));
72
72
  if(FileHandler.exists(clientIndexPath)){
73
73
  clearInterval(interval);
74
74
  resolve();
75
75
  return;
76
76
  }
77
- if(Date.now() - startTime > this.maxWaitTime){
77
+ if(awaitTime > this.maxWaitTime){
78
78
  clearInterval(interval);
79
79
  Logger.warning('Schema generation wait timeout reached.');
80
80
  resolve();
@@ -83,6 +83,17 @@ class PrismaSchemaGenerator
83
83
  });
84
84
  }
85
85
 
86
+ resolveClientPath(clientPath)
87
+ {
88
+ if(clientPath.match(/^[a-zA-Z]:/) || clientPath.startsWith('/')){
89
+ return clientPath;
90
+ }
91
+ if(clientPath.startsWith('node_modules')){
92
+ return FileHandler.joinPaths(process.cwd(), clientPath);
93
+ }
94
+ return FileHandler.joinPaths(this.prismaSchemaPath, clientPath);
95
+ }
96
+
86
97
  generateSchemaFile()
87
98
  {
88
99
  let datasourceProvider = this.getDatasourceProvider();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@reldens/storage",
3
3
  "scope": "@reldens",
4
- "version": "0.55.0",
4
+ "version": "0.57.0",
5
5
  "description": "Reldens - Storage",
6
6
  "author": "Damian A. Pastorini",
7
7
  "license": "MIT",
@@ -45,13 +45,13 @@
45
45
  "@mikro-orm/core": "^6.4.16",
46
46
  "@mikro-orm/mongodb": "^6.4.16",
47
47
  "@mikro-orm/mysql": "^6.4.16",
48
- "@prisma/client": "^6.9.0",
48
+ "@prisma/client": "^6.10.0",
49
49
  "@reldens/server-utils": "^0.19.0",
50
50
  "@reldens/utils": "^0.50.0",
51
51
  "knex": "^3.1.0",
52
52
  "mysql": "^2.18.1",
53
53
  "mysql2": "^3.14.1",
54
54
  "objection": "^3.1.5",
55
- "prisma": "^6.9.0"
55
+ "prisma": "^6.10.0"
56
56
  }
57
57
  }