refactor: prepare for MikroORM storage support
[e-mobility-charging-stations-simulator.git] / src / performance / storage / MikroOrmStorage.ts
index 4e2091a52401e91f85a534ac0b0466d8cd5cbf00..9746c6bd5f5a09b439129338fc1dde2a1a82a013 100644 (file)
@@ -1,27 +1,15 @@
-// Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+// Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
 
-import {
-  type Configuration,
-  type Connection,
-  type IDatabaseDriver,
-  MikroORM,
-  type Options
-} from '@mikro-orm/core'
-import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
+import { MikroORM as MariaDbORM, type Options as MariaDbOptions } from '@mikro-orm/mariadb'
+import { MikroORM as SqliteORM, type Options as SqliteOptions } from '@mikro-orm/sqlite'
 
 import { Storage } from './Storage.js'
-import {
-  type MikroOrmDbType,
-  PerformanceData,
-  PerformanceRecord,
-  type Statistics,
-  StorageType
-} from '../../types/index.js'
+import { type PerformanceRecord, type Statistics, StorageType } from '../../types/index.js'
 import { Constants } from '../../utils/index.js'
 
 export class MikroOrmStorage extends Storage {
   private readonly storageType: StorageType
-  private orm?: MikroORM
+  private orm?: SqliteORM | MariaDbORM
 
   constructor (storageUri: string, logPrefix: string, storageType: StorageType) {
     super(storageUri, logPrefix)
@@ -31,8 +19,13 @@ export class MikroOrmStorage extends Storage {
 
   public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
     try {
-      const performanceRecord = new PerformanceRecord()
-      await this.orm?.em.persistAndFlush(performanceRecord)
+      await this.orm?.em.persistAndFlush({
+        ...performanceStatistics,
+        statisticsData: Array.from(performanceStatistics.statisticsData, ([name, value]) => ({
+          name,
+          ...value
+        }))
+      } satisfies PerformanceRecord)
     } catch (error) {
       this.handleDBError(this.storageType, error as Error, Constants.PERFORMANCE_RECORDS_TABLE)
     }
@@ -40,8 +33,16 @@ export class MikroOrmStorage extends Storage {
 
   public async open (): Promise<void> {
     try {
-      if (this?.orm == null) {
-        this.orm = await MikroORM.init(this.getOptions(), true)
+      if (this.orm == null) {
+        switch (this.storageType) {
+          case StorageType.SQLITE:
+            this.orm = await SqliteORM.init(this.getOptions() as SqliteOptions)
+            break
+          case StorageType.MARIA_DB:
+          case StorageType.MYSQL:
+            this.orm = await MariaDbORM.init(this.getOptions() as MariaDbOptions)
+            break
+        }
       }
     } catch (error) {
       this.handleDBError(this.storageType, error as Error)
@@ -50,9 +51,9 @@ export class MikroOrmStorage extends Storage {
 
   public async close (): Promise<void> {
     try {
-      if (this?.orm != null) {
+      if (this.orm != null) {
         await this.orm.close()
-        delete this?.orm
+        delete this.orm
       }
     } catch (error) {
       this.handleDBError(this.storageType, error as Error)
@@ -61,21 +62,16 @@ export class MikroOrmStorage extends Storage {
 
   private getDBName (): string {
     if (this.storageType === StorageType.SQLITE) {
-      return `${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`
+      return `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`
     }
-    return (
-      this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '') ??
-      Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME
-    )
+    return this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '')
   }
 
-  private getOptions ():
-  | Configuration<IDatabaseDriver<Connection>>
-  | Options<IDatabaseDriver<Connection>> {
+  private getOptions (): SqliteOptions | MariaDbOptions {
     return {
-      metadataProvider: TsMorphMetadataProvider,
-      entities: [PerformanceRecord, PerformanceData],
-      type: this.storageType as MikroOrmDbType,
+      dbName: this.dbName,
+      entities: ['./dist/types/orm/entities/*.js'],
+      entitiesTs: ['./src/types/orm/entities/*.ts'],
       clientUrl: this.getClientUrl()
     }
   }