refactor(simulator): remove duplicated code in utils
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 14 Feb 2023 14:40:47 +0000 (15:40 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 14 Feb 2023 14:40:47 +0000 (15:40 +0100)
use the internal module export/import pattern without introducing nasty
circular dependencies

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ChargingStation.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/types/ChargingStationTemplate.ts
src/utils/Configuration.ts
src/utils/Utils.ts

index ef2c3a14b3efaf1ada9495dca50719051b35cfc6..5d7acc669f89e82aa86d62a14319b38be1f4b3d7 100644 (file)
@@ -35,8 +35,7 @@ import { OCPP16ResponseService } from './ocpp/1.6/OCPP16ResponseService';
 import { OCPP20ResponseService } from './ocpp/2.0/OCPP20ResponseService';
 import { OCPPServiceUtils } from './ocpp/OCPPServiceUtils';
 import { BaseError, OCPPError } from '../exception';
-// import { PerformanceStatistics } from '../performance';
-import { PerformanceStatistics } from '../performance/PerformanceStatistics';
+import { PerformanceStatistics } from '../performance';
 import {
   type AutomaticTransactionGeneratorConfiguration,
   AvailabilityType,
index f4299226115029a41a7271c063e14ae44209f2ac..0f05d9a3d53082f210eaf93c1225ed04b78f2d0a 100644 (file)
@@ -4,8 +4,7 @@ import ajvFormats from 'ajv-formats';
 import { type OCPPResponseService, OCPPServiceUtils } from './internal';
 import type { ChargingStation } from '../../charging-station';
 import { OCPPError } from '../../exception';
-// import { PerformanceStatistics } from '../../performance';
-import { PerformanceStatistics } from '../../performance/PerformanceStatistics';
+import { PerformanceStatistics } from '../../performance';
 import {
   type EmptyObject,
   type ErrorCallback,
index 36a481ff6ed41299ea5c69bcca64767438b55eee..aa9a1b7a200f9a32be746236f5b6f0c3d495cda9 100644 (file)
@@ -1,4 +1,4 @@
-import type { ClientRequestArgs } from 'http';
+import type { ClientRequestArgs } from 'node:http';
 
 import type { ClientOptions } from 'ws';
 
index 725dd2e1466bd5ae3df9ecfba8e0e54251963de7..6f1705a69b813082cd62e2850153a357374d1337 100644 (file)
@@ -6,13 +6,11 @@ import chalk from 'chalk';
 import merge from 'just-merge';
 import { WorkerChoiceStrategies } from 'poolifier';
 
-import { Constants } from './internal';
+import { Constants, FileUtils, Utils } from './internal';
 import {
   ApplicationProtocol,
   type ConfigurationData,
-  type EmptyObject,
   FileType,
-  type HandleErrorParams,
   type StationTemplateUrl,
   type StorageConfiguration,
   StorageType,
@@ -48,13 +46,13 @@ export class Configuration {
       "Use 'logStatisticsInterval' instead"
     );
     // Read conf
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logStatisticsInterval')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logStatisticsInterval')
       ? Configuration.getConfig()?.logStatisticsInterval
       : Constants.DEFAULT_LOG_STATISTICS_INTERVAL;
   }
 
   static getUIServer(): UIServerConfiguration {
-    if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'uiWebSocketServer')) {
+    if (Utils.objectHasOwnProperty(Configuration.getConfig(), 'uiWebSocketServer')) {
       console.error(
         chalk`{green ${Configuration.logPrefix()}} {red Deprecated configuration section 'uiWebSocketServer' usage. Use 'uiServer' instead}`
       );
@@ -67,13 +65,13 @@ export class Configuration {
         port: Constants.DEFAULT_UI_SERVER_PORT,
       },
     };
-    if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'uiServer')) {
+    if (Utils.objectHasOwnProperty(Configuration.getConfig(), 'uiServer')) {
       uiServerConfiguration = merge<UIServerConfiguration>(
         uiServerConfiguration,
         Configuration.getConfig()?.uiServer
       );
     }
-    if (Configuration.isCFEnvironment() === true) {
+    if (Utils.isCFEnvironment() === true) {
       delete uiServerConfiguration.options?.host;
       uiServerConfiguration.options.port = parseInt(process.env.PORT);
     }
@@ -87,7 +85,7 @@ export class Configuration {
       type: StorageType.JSON_FILE,
       uri: this.getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
     };
-    if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'performanceStorage')) {
+    if (Utils.objectHasOwnProperty(Configuration.getConfig(), 'performanceStorage')) {
       storageConfiguration = {
         ...storageConfiguration,
         ...Configuration.getConfig()?.performanceStorage,
@@ -113,7 +111,7 @@ export class Configuration {
       'Use it in charging station template instead'
     );
     // Read conf
-    if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'autoReconnectMaxRetries')) {
+    if (Utils.objectHasOwnProperty(Configuration.getConfig(), 'autoReconnectMaxRetries')) {
       return Configuration.getConfig()?.autoReconnectMaxRetries;
     }
   }
@@ -124,12 +122,12 @@ export class Configuration {
       undefined,
       "Use 'stationTemplateUrls' instead"
     );
-    !Configuration.isUndefined(Configuration.getConfig()['stationTemplateURLs']) &&
+    !Utils.isUndefined(Configuration.getConfig()['stationTemplateURLs']) &&
       (Configuration.getConfig().stationTemplateUrls = Configuration.getConfig()[
         'stationTemplateURLs'
       ] as unknown as StationTemplateUrl[]);
     Configuration.getConfig().stationTemplateUrls.forEach((stationUrl: StationTemplateUrl) => {
-      if (!Configuration.isUndefined(stationUrl['numberOfStation'])) {
+      if (!Utils.isUndefined(stationUrl['numberOfStation'])) {
         console.error(
           chalk`{green ${Configuration.logPrefix()}} {red Deprecated configuration key 'numberOfStation' usage for template file '${
             stationUrl.file
@@ -188,40 +186,31 @@ export class Configuration {
       "Use 'worker' section to define the worker pool strategy instead"
     );
     let workerConfiguration: WorkerConfiguration = {
-      processType: Configuration.objectHasOwnProperty(Configuration.getConfig(), 'workerProcess')
+      processType: Utils.objectHasOwnProperty(Configuration.getConfig(), 'workerProcess')
         ? Configuration.getConfig()?.workerProcess
         : WorkerProcessType.WORKER_SET,
-      startDelay: Configuration.objectHasOwnProperty(Configuration.getConfig(), 'workerStartDelay')
+      startDelay: Utils.objectHasOwnProperty(Configuration.getConfig(), 'workerStartDelay')
         ? Configuration.getConfig()?.workerStartDelay
         : WorkerConstants.DEFAULT_WORKER_START_DELAY,
-      elementsPerWorker: Configuration.objectHasOwnProperty(
+      elementsPerWorker: Utils.objectHasOwnProperty(
         Configuration.getConfig(),
         'chargingStationsPerWorker'
       )
         ? Configuration.getConfig()?.chargingStationsPerWorker
         : WorkerConstants.DEFAULT_ELEMENTS_PER_WORKER,
-      elementStartDelay: Configuration.objectHasOwnProperty(
-        Configuration.getConfig(),
-        'elementStartDelay'
-      )
+      elementStartDelay: Utils.objectHasOwnProperty(Configuration.getConfig(), 'elementStartDelay')
         ? Configuration.getConfig()?.elementStartDelay
         : WorkerConstants.DEFAULT_ELEMENT_START_DELAY,
-      poolMinSize: Configuration.objectHasOwnProperty(
-        Configuration.getConfig(),
-        'workerPoolMinSize'
-      )
+      poolMinSize: Utils.objectHasOwnProperty(Configuration.getConfig(), 'workerPoolMinSize')
         ? Configuration.getConfig()?.workerPoolMinSize
         : WorkerConstants.DEFAULT_POOL_MIN_SIZE,
-      poolMaxSize: Configuration.objectHasOwnProperty(
-        Configuration.getConfig(),
-        'workerPoolMaxSize'
-      )
+      poolMaxSize: Utils.objectHasOwnProperty(Configuration.getConfig(), 'workerPoolMaxSize')
         ? Configuration.getConfig()?.workerPoolMaxSize
         : WorkerConstants.DEFAULT_POOL_MAX_SIZE,
       poolStrategy:
         Configuration.getConfig()?.workerPoolStrategy ?? WorkerChoiceStrategies.ROUND_ROBIN,
     };
-    if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'worker')) {
+    if (Utils.objectHasOwnProperty(Configuration.getConfig(), 'worker')) {
       workerConfiguration = { ...workerConfiguration, ...Configuration.getConfig()?.worker };
     }
     return workerConfiguration;
@@ -233,45 +222,45 @@ export class Configuration {
       undefined,
       "Use 'logConsole' instead"
     );
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logConsole')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logConsole')
       ? Configuration.getConfig()?.logConsole
       : false;
   }
 
   static getLogFormat(): string | undefined {
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logFormat')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logFormat')
       ? Configuration.getConfig()?.logFormat
       : 'simple';
   }
 
   static getLogRotate(): boolean | undefined {
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logRotate')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logRotate')
       ? Configuration.getConfig()?.logRotate
       : true;
   }
 
   static getLogMaxFiles(): number | string | false | undefined {
     return (
-      Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logMaxFiles') &&
+      Utils.objectHasOwnProperty(Configuration.getConfig(), 'logMaxFiles') &&
       Configuration.getConfig()?.logMaxFiles
     );
   }
 
   static getLogMaxSize(): number | string | false | undefined {
     return (
-      Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logMaxFiles') &&
+      Utils.objectHasOwnProperty(Configuration.getConfig(), 'logMaxFiles') &&
       Configuration.getConfig()?.logMaxSize
     );
   }
 
   static getLogLevel(): string | undefined {
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logLevel')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logLevel')
       ? Configuration.getConfig()?.logLevel?.toLowerCase()
       : 'info';
   }
 
   static getLogFile(): string | undefined {
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logFile')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logFile')
       ? Configuration.getConfig()?.logFile
       : 'combined.log';
   }
@@ -282,7 +271,7 @@ export class Configuration {
       undefined,
       "Use 'logErrorFile' instead"
     );
-    return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logErrorFile')
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logErrorFile')
       ? Configuration.getConfig()?.logErrorFile
       : 'error.log';
   }
@@ -293,7 +282,7 @@ export class Configuration {
       undefined,
       "Use 'supervisionUrls' instead"
     );
-    !Configuration.isUndefined(Configuration.getConfig()['supervisionURLs']) &&
+    !Utils.isUndefined(Configuration.getConfig()['supervisionURLs']) &&
       (Configuration.getConfig().supervisionUrls = Configuration.getConfig()['supervisionURLs'] as
         | string
         | string[]);
@@ -312,10 +301,7 @@ export class Configuration {
       undefined,
       "Use 'supervisionUrlDistribution' instead"
     );
-    return Configuration.objectHasOwnProperty(
-      Configuration.getConfig(),
-      'supervisionUrlDistribution'
-    )
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'supervisionUrlDistribution')
       ? Configuration.getConfig()?.supervisionUrlDistribution
       : SupervisionUrlDistribution.ROUND_ROBIN;
   }
@@ -331,17 +317,15 @@ export class Configuration {
   ) {
     if (
       sectionName &&
-      !Configuration.isUndefined(Configuration.getConfig()[sectionName]) &&
-      !Configuration.isUndefined(
-        (Configuration.getConfig()[sectionName] as Record<string, unknown>)[key]
-      )
+      !Utils.isUndefined(Configuration.getConfig()[sectionName]) &&
+      !Utils.isUndefined((Configuration.getConfig()[sectionName] as Record<string, unknown>)[key])
     ) {
       console.error(
         chalk`{green ${Configuration.logPrefix()}} {red Deprecated configuration key '${key}' usage in section '${sectionName}'${
           logMsgToAppend.trim().length > 0 && `. ${logMsgToAppend}`
         }}`
       );
-    } else if (!Configuration.isUndefined(Configuration.getConfig()[key])) {
+    } else if (!Utils.isUndefined(Configuration.getConfig()[key])) {
       console.error(
         chalk`{green ${Configuration.logPrefix()}} {red Deprecated configuration key '${key}' usage${
           logMsgToAppend.trim().length > 0 && `. ${logMsgToAppend}`
@@ -358,11 +342,12 @@ export class Configuration {
           fs.readFileSync(Configuration.configurationFile, 'utf8')
         ) as ConfigurationData;
       } catch (error) {
-        Configuration.handleFileException(
+        FileUtils.handleFileException(
           Configuration.configurationFile,
           FileType.Configuration,
           error as NodeJS.ErrnoException,
-          Configuration.logPrefix()
+          Configuration.logPrefix(),
+          { consoleOut: true }
         );
       }
       if (!Configuration.configurationFileWatcher) {
@@ -378,7 +363,7 @@ export class Configuration {
         if (filename?.trim().length > 0 && event === 'change') {
           // Nullify to force configuration file reading
           Configuration.configuration = null;
-          if (!Configuration.isUndefined(Configuration.configurationChangeCallback)) {
+          if (!Utils.isUndefined(Configuration.configurationChangeCallback)) {
             Configuration.configurationChangeCallback().catch((error) => {
               throw typeof error === 'string' ? new Error(error) : error;
             });
@@ -386,19 +371,16 @@ export class Configuration {
         }
       });
     } catch (error) {
-      Configuration.handleFileException(
+      FileUtils.handleFileException(
         Configuration.configurationFile,
         FileType.Configuration,
         error as NodeJS.ErrnoException,
-        Configuration.logPrefix()
+        Configuration.logPrefix(),
+        { consoleOut: true }
       );
     }
   }
 
-  private static isCFEnvironment(): boolean {
-    return process.env.VCAP_APPLICATION !== undefined;
-  }
-
   private static getDefaultPerformanceStorageUri(storageType: StorageType) {
     switch (storageType) {
       case StorageType.JSON_FILE:
@@ -415,40 +397,4 @@ export class Configuration {
         throw new Error(`Performance storage URI is mandatory with storage type '${storageType}'`);
     }
   }
-
-  private static objectHasOwnProperty(object: unknown, property: string): boolean {
-    return Object.prototype.hasOwnProperty.call(object, property) as boolean;
-  }
-
-  private static isUndefined(obj: unknown): boolean {
-    return obj === undefined;
-  }
-
-  private static handleFileException(
-    filePath: string,
-    fileType: FileType,
-    error: NodeJS.ErrnoException,
-    logPrefix: string,
-    params: HandleErrorParams<EmptyObject> = { throwError: true }
-  ): void {
-    const prefix = logPrefix?.trim().length > 0 ? `${logPrefix} ` : '';
-    let logMsg: string;
-    switch (error.code) {
-      case 'ENOENT':
-        logMsg = `${fileType} file ${filePath} not found: `;
-        break;
-      case 'EEXIST':
-        logMsg = `${fileType} file ${filePath} already exists: `;
-        break;
-      case 'EACCES':
-        logMsg = `${fileType} file ${filePath} access denied: `;
-        break;
-      default:
-        logMsg = `${fileType} file ${filePath} error: `;
-    }
-    console.error(`${chalk.green(prefix)}${chalk.red(logMsg)}`, error);
-    if (params?.throwError) {
-      throw error;
-    }
-  }
 }
index bac9705da1ba8e37f67418f86aebbc630529595e..bffa0a17982fb7b9364cee51ad6cadeb84f096da 100644 (file)
@@ -185,6 +185,16 @@ export class Utils {
     return clone<T>(object);
   }
 
+  public static objectHasOwnProperty(object: object, property: string): boolean {
+    return (
+      Utils.isObject(object) && (Object.prototype.hasOwnProperty.call(object, property) as boolean)
+    );
+  }
+
+  public static isCFEnvironment(): boolean {
+    return process.env.VCAP_APPLICATION !== undefined;
+  }
+
   public static isIterable<T>(obj: T): boolean {
     return !Utils.isNullOrUndefined(obj) ? typeof obj[Symbol.iterator] === 'function' : false;
   }