refactor: add more sanity checks to charging profiles handling code
[e-mobility-charging-stations-simulator.git] / src / utils / Configuration.ts
index 66abd3e101dc6e427cac6c5c35babe61d9fdd02e..f03e0472570ec0af65a1a0dd070d57a8131fd911 100644 (file)
@@ -22,6 +22,12 @@ import {
 } from '../types';
 import { WorkerConstants, WorkerProcessType } from '../worker';
 
+type ConfigurationSectionType =
+  | LogConfiguration
+  | StorageConfiguration
+  | WorkerConfiguration
+  | UIServerConfiguration;
+
 export class Configuration {
   private static configurationFile = join(
     dirname(fileURLToPath(import.meta.url)),
@@ -29,11 +35,11 @@ export class Configuration {
     'config.json',
   );
 
-  private static configurationFileWatcher: FSWatcher | undefined;
-  private static configurationData: ConfigurationData | null = null;
+  private static configurationFileWatcher?: FSWatcher;
+  private static configurationData?: ConfigurationData;
   private static configurationSectionCache = new Map<
     ConfigurationSection,
-    LogConfiguration | StorageConfiguration | WorkerConfiguration | UIServerConfiguration
+    ConfigurationSectionType
   >([
     [ConfigurationSection.log, Configuration.buildLogSection()],
     [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()],
@@ -51,7 +57,9 @@ export class Configuration {
     Configuration.configurationChangeCallback = cb;
   }
 
-  public static getConfigurationSection<T>(sectionName: ConfigurationSection): T {
+  public static getConfigurationSection<T extends ConfigurationSectionType>(
+    sectionName: ConfigurationSection,
+  ): T {
     if (!Configuration.configurationSectionCache.has(sectionName)) {
       switch (sectionName) {
         case ConfigurationSection.log:
@@ -111,16 +119,18 @@ export class Configuration {
       "Use 'stationTemplateUrls' instead",
     );
     // eslint-disable-next-line @typescript-eslint/dot-notation
-    !isUndefined(Configuration.getConfigurationData()!['stationTemplateURLs']) &&
+    !isUndefined(
+      Configuration.getConfigurationData()!['stationTemplateURLs' as keyof ConfigurationData],
+    ) &&
       (Configuration.getConfigurationData()!.stationTemplateUrls =
         Configuration.getConfigurationData()![
           // eslint-disable-next-line @typescript-eslint/dot-notation
-          'stationTemplateURLs'
+          'stationTemplateURLs' as keyof ConfigurationData
         ] as StationTemplateUrl[]);
     Configuration.getConfigurationData()!.stationTemplateUrls.forEach(
       (stationTemplateUrl: StationTemplateUrl) => {
         // eslint-disable-next-line @typescript-eslint/dot-notation
-        if (!isUndefined(stationTemplateUrl['numberOfStation'])) {
+        if (!isUndefined(stationTemplateUrl['numberOfStation' as keyof StationTemplateUrl])) {
           console.error(
             `${chalk.green(Configuration.logPrefix())} ${chalk.red(
               `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`,
@@ -139,10 +149,14 @@ export class Configuration {
       "Use 'supervisionUrls' instead",
     );
     // eslint-disable-next-line @typescript-eslint/dot-notation
-    if (!isUndefined(Configuration.getConfigurationData()!['supervisionURLs'])) {
+    if (
+      !isUndefined(
+        Configuration.getConfigurationData()!['supervisionURLs' as keyof ConfigurationData],
+      )
+    ) {
       Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![
         // eslint-disable-next-line @typescript-eslint/dot-notation
-        'supervisionURLs'
+        'supervisionURLs' as keyof ConfigurationData
       ] as string | string[];
     }
     return Configuration.getConfigurationData()?.supervisionUrls;
@@ -212,7 +226,7 @@ export class Configuration {
     let storageConfiguration: StorageConfiguration = {
       enabled: false,
       type: StorageType.JSON_FILE,
-      uri: this.getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
+      uri: Configuration.getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
     };
     if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.performanceStorage)) {
       storageConfiguration = {
@@ -437,9 +451,14 @@ export class Configuration {
   ) {
     if (
       sectionName &&
-      !isUndefined(Configuration.getConfigurationData()![sectionName]) &&
+      !isUndefined(Configuration.getConfigurationData()![sectionName as keyof ConfigurationData]) &&
       !isUndefined(
-        (Configuration.getConfigurationData()![sectionName] as Record<string, unknown>)[key],
+        (
+          Configuration.getConfigurationData()![sectionName as keyof ConfigurationData] as Record<
+            string,
+            unknown
+          >
+        )[key],
       )
     ) {
       console.error(
@@ -449,7 +468,9 @@ export class Configuration {
           }`,
         )}`,
       );
-    } else if (!isUndefined(Configuration.getConfigurationData()![key])) {
+    } else if (
+      !isUndefined(Configuration.getConfigurationData()![key as keyof ConfigurationData])
+    ) {
       console.error(
         `${chalk.green(Configuration.logPrefix())} ${chalk.red(
           `Deprecated configuration key '${key}' usage${
@@ -460,12 +481,15 @@ export class Configuration {
     }
   }
 
-  private static getConfigurationData(): ConfigurationData | null {
+  private static getConfigurationData(): ConfigurationData | undefined {
     if (!Configuration.configurationData) {
       try {
         Configuration.configurationData = JSON.parse(
           readFileSync(Configuration.configurationFile, 'utf8'),
         ) as ConfigurationData;
+        if (!Configuration.configurationFileWatcher) {
+          Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher();
+        }
       } catch (error) {
         Configuration.handleFileException(
           Configuration.configurationFile,
@@ -474,9 +498,6 @@ export class Configuration {
           Configuration.logPrefix(),
         );
       }
-      if (!Configuration.configurationFileWatcher) {
-        Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher();
-      }
     }
     return Configuration.configurationData;
   }
@@ -485,8 +506,7 @@ export class Configuration {
     try {
       return watch(Configuration.configurationFile, (event, filename): void => {
         if (filename!.trim()!.length > 0 && event === 'change') {
-          // Nullify to force configuration file reading
-          Configuration.configurationData = null;
+          delete Configuration.configurationData;
           Configuration.configurationSectionCache.clear();
           if (!isUndefined(Configuration.configurationChangeCallback)) {
             Configuration.configurationChangeCallback().catch((error) => {