Merge pull request #732 from SAP/combined-prs-branch
[e-mobility-charging-stations-simulator.git] / src / utils / Configuration.ts
index b9fc7bd67ca8a778a30c632f55f1806119766960..0c5a356ac18cd35a0e9e201b3f910bed3f6ce5b2 100644 (file)
@@ -6,7 +6,14 @@ import chalk from 'chalk';
 import merge from 'just-merge';
 
 import { Constants } from './Constants';
-import { hasOwnProp, isCFEnvironment, isNotEmptyString, isUndefined } from './Utils';
+import {
+  hasOwnProp,
+  isCFEnvironment,
+  isNotEmptyString,
+  isUndefined,
+  logPrefix,
+  once,
+} from './Utils';
 import {
   ApplicationProtocol,
   type ConfigurationData,
@@ -35,6 +42,8 @@ type ConfigurationSectionType =
   | UIServerConfiguration;
 
 export class Configuration {
+  public static configurationChangeCallback: () => Promise<void>;
+
   private static configurationFile = join(
     dirname(fileURLToPath(import.meta.url)),
     'assets',
@@ -53,18 +62,10 @@ export class Configuration {
     [ConfigurationSection.uiServer, Configuration.buildUIServerSection()],
   ]);
 
-  private static warnDeprecatedConfigurationKeys = false;
-
-  private static configurationChangeCallback?: () => Promise<void>;
-
   private constructor() {
     // This is intentional
   }
 
-  public static setConfigurationChangeCallback(cb: () => Promise<void>): void {
-    Configuration.configurationChangeCallback = cb;
-  }
-
   public static getConfigurationSection<T extends ConfigurationSectionType>(
     sectionName: ConfigurationSection,
   ): T {
@@ -74,21 +75,19 @@ export class Configuration {
     return Configuration.configurationSectionCache.get(sectionName) as T;
   }
 
-  public static getAutoReconnectMaxRetries(): number | undefined {
-    if (hasOwnProp(Configuration.getConfigurationData(), 'autoReconnectMaxRetries')) {
-      return Configuration.getConfigurationData()?.autoReconnectMaxRetries;
-    }
-  }
-
   public static getStationTemplateUrls(): StationTemplateUrl[] | undefined {
-    Configuration.checkDeprecatedConfigurationKeys();
+    const checkDeprecatedConfigurationKeysOnce = once(
+      Configuration.checkDeprecatedConfigurationKeys.bind(Configuration),
+      Configuration,
+    );
+    checkDeprecatedConfigurationKeysOnce();
     return Configuration.getConfigurationData()?.stationTemplateUrls;
   }
 
   public static getSupervisionUrls(): string | string[] | undefined {
     if (
       !isUndefined(
-        Configuration.getConfigurationData()!['supervisionURLs' as keyof ConfigurationData],
+        Configuration.getConfigurationData()?.['supervisionURLs' as keyof ConfigurationData],
       )
     ) {
       Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![
@@ -105,7 +104,7 @@ export class Configuration {
   }
 
   public static workerPoolInUse(): boolean {
-    return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes(
+    return [WorkerProcessType.dynamicPool, WorkerProcessType.fixedPool].includes(
       Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
         .processType!,
     );
@@ -118,6 +117,10 @@ export class Configuration {
     );
   }
 
+  private static logPrefix = (): string => {
+    return logPrefix(' Simulator configuration |');
+  };
+
   private static isConfigurationSectionCached(sectionName: ConfigurationSection): boolean {
     return Configuration.configurationSectionCache.has(sectionName);
   }
@@ -291,14 +294,7 @@ export class Configuration {
     return workerConfiguration;
   }
 
-  private static logPrefix = (): string => {
-    return `${new Date().toLocaleString()} Simulator configuration |`;
-  };
-
   private static checkDeprecatedConfigurationKeys() {
-    if (Configuration.warnDeprecatedConfigurationKeys) {
-      return;
-    }
     // connection timeout
     Configuration.warnDeprecatedConfigurationKey(
       'autoReconnectTimeout',
@@ -323,15 +319,15 @@ export class Configuration {
       "Use 'stationTemplateUrls' instead",
     );
     !isUndefined(
-      Configuration.getConfigurationData()!['stationTemplateURLs' as keyof ConfigurationData],
+      Configuration.getConfigurationData()?.['stationTemplateURLs' as keyof ConfigurationData],
     ) &&
       (Configuration.getConfigurationData()!.stationTemplateUrls =
         Configuration.getConfigurationData()![
           'stationTemplateURLs' as keyof ConfigurationData
         ] as StationTemplateUrl[]);
-    Configuration.getConfigurationData()!.stationTemplateUrls.forEach(
+    Configuration.getConfigurationData()?.stationTemplateUrls.forEach(
       (stationTemplateUrl: StationTemplateUrl) => {
-        if (!isUndefined(stationTemplateUrl['numberOfStation' as keyof StationTemplateUrl])) {
+        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`,
@@ -389,17 +385,17 @@ export class Configuration {
       `Use '${ConfigurationSection.worker}' section to define the worker pool minimum size instead`,
     );
     Configuration.warnDeprecatedConfigurationKey(
-      'workerPoolSize;',
+      'workerPoolSize',
       undefined,
       `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
     );
     Configuration.warnDeprecatedConfigurationKey(
-      'workerPoolMaxSize;',
+      'workerPoolMaxSize',
       undefined,
       `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
     );
     Configuration.warnDeprecatedConfigurationKey(
-      'workerPoolStrategy;',
+      'workerPoolStrategy',
       undefined,
       `Use '${ConfigurationSection.worker}' section to define the worker pool strategy instead`,
     );
@@ -408,6 +404,16 @@ export class Configuration {
       ConfigurationSection.worker,
       'Not publicly exposed to end users',
     );
+    if (
+      Configuration.getConfigurationData()?.worker?.processType ===
+      ('staticPool' as WorkerProcessType)
+    ) {
+      console.error(
+        `${chalk.green(Configuration.logPrefix())} ${chalk.red(
+          `Deprecated configuration 'staticPool' value usage in worker section 'processType' field. Use '${WorkerProcessType.fixedPool}' value instead`,
+        )}`,
+      );
+    }
     // log section
     Configuration.warnDeprecatedConfigurationKey(
       'logEnabled',
@@ -473,7 +479,6 @@ export class Configuration {
         )}`,
       );
     }
-    Configuration.warnDeprecatedConfigurationKeys = true;
   }
 
   private static warnDeprecatedConfigurationKey(
@@ -483,14 +488,16 @@ export class Configuration {
   ) {
     if (
       sectionName &&
-      !isUndefined(Configuration.getConfigurationData()![sectionName as keyof ConfigurationData]) &&
+      !isUndefined(
+        Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData],
+      ) &&
       !isUndefined(
         (
-          Configuration.getConfigurationData()![sectionName as keyof ConfigurationData] as Record<
+          Configuration.getConfigurationData()?.[sectionName as keyof ConfigurationData] as Record<
             string,
             unknown
           >
-        )[key],
+        )?.[key],
       )
     ) {
       console.error(
@@ -501,7 +508,7 @@ export class Configuration {
         )}`,
       );
     } else if (
-      !isUndefined(Configuration.getConfigurationData()![key as keyof ConfigurationData])
+      !isUndefined(Configuration.getConfigurationData()?.[key as keyof ConfigurationData])
     ) {
       console.error(
         `${chalk.green(Configuration.logPrefix())} ${chalk.red(
@@ -541,7 +548,7 @@ export class Configuration {
           delete Configuration.configurationData;
           Configuration.configurationSectionCache.clear();
           if (!isUndefined(Configuration.configurationChangeCallback)) {
-            Configuration.configurationChangeCallback!().catch((error) => {
+            Configuration.configurationChangeCallback().catch((error) => {
               throw typeof error === 'string' ? new Error(error) : error;
             });
           }
@@ -561,27 +568,27 @@ export class Configuration {
     file: string,
     fileType: FileType,
     error: NodeJS.ErrnoException,
-    logPrefix: string,
+    logPfx: string,
   ): void {
-    const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
+    const prefix = isNotEmptyString(logPfx) ? `${logPfx} ` : '';
     let logMsg: string;
     switch (error.code) {
       case 'ENOENT':
-        logMsg = `${fileType} file ${file} not found:`;
+        logMsg = `${fileType} file ${file} not found: `;
         break;
       case 'EEXIST':
-        logMsg = `${fileType} file ${file} already exists:`;
+        logMsg = `${fileType} file ${file} already exists: `;
         break;
       case 'EACCES':
-        logMsg = `${fileType} file ${file} access denied:`;
+        logMsg = `${fileType} file ${file} access denied: `;
         break;
       case 'EPERM':
-        logMsg = `${fileType} file ${file} permission denied:`;
+        logMsg = `${fileType} file ${file} permission denied: `;
         break;
       default:
-        logMsg = `${fileType} file ${file} error:`;
+        logMsg = `${fileType} file ${file} error: `;
     }
-    console.error(`${chalk.green(prefix)}${chalk.red(`${logMsg} `)}`, error);
+    console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error);
     throw error;
   }