refactor: split Utils static methods class into functions
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 5 Jul 2023 14:43:08 +0000 (16:43 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Wed, 5 Jul 2023 14:43:08 +0000 (16:43 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
32 files changed:
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/Bootstrap.ts
src/charging-station/ChargingStation.ts
src/charging-station/ChargingStationUtils.ts
src/charging-station/IdTagsCache.ts
src/charging-station/SharedLRUCache.ts
src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/broadcast-channel/UIServiceWorkerBroadcastChannel.ts
src/charging-station/broadcast-channel/WorkerBroadcastChannel.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16RequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts
src/charging-station/ocpp/2.0/OCPP20RequestService.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/charging-station/ocpp/OCPPServiceUtils.ts
src/charging-station/ui-server/UIHttpServer.ts
src/charging-station/ui-server/UIServerUtils.ts
src/charging-station/ui-server/UIWebSocketServer.ts
src/charging-station/ui-server/ui-services/AbstractUIService.ts
src/performance/PerformanceStatistics.ts
src/performance/storage/JsonFileStorage.ts
src/performance/storage/Storage.ts
src/utils/ChargingStationConfigurationUtils.ts
src/utils/Configuration.ts
src/utils/ErrorUtils.ts
src/utils/FileUtils.ts
src/utils/Logger.ts
src/utils/StatisticUtils.ts
src/utils/Utils.ts
src/utils/index.ts
test/utils/Utils.test.ts

index 0389526fd6a9400a90404903a360d8d607448fd6..233f2519dcb4c8b120fe20d74293505af9c38761 100644 (file)
@@ -19,7 +19,17 @@ import {
   StopTransactionReason,
   type StopTransactionResponse,
 } from '../types';
-import { Constants, Utils, logger } from '../utils';
+import {
+  Constants,
+  cloneObject,
+  formatDurationMilliSeconds,
+  getRandomInteger,
+  isNullOrUndefined,
+  logPrefix,
+  logger,
+  secureRandom,
+  sleep,
+} from '../utils';
 
 const moduleName = 'AutomaticTransactionGenerator';
 
@@ -179,7 +189,7 @@ export class AutomaticTransactionGenerator extends AsyncResource {
     logger.info(
       `${this.logPrefix(
         connectorId
-      )} started on connector and will run for ${Utils.formatDurationMilliSeconds(
+      )} started on connector and will run for ${formatDurationMilliSeconds(
         this.connectorsStatus.get(connectorId).stopDate.getTime() -
           this.connectorsStatus.get(connectorId).startDate.getTime()
       )}`
@@ -235,21 +245,19 @@ export class AutomaticTransactionGenerator extends AsyncResource {
           )} transaction loop waiting for charging station service to be initialized`
         );
         do {
-          await Utils.sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME);
+          await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME);
         } while (!this.chargingStation?.ocppRequestService);
       }
       const wait =
-        Utils.getRandomInteger(
+        getRandomInteger(
           this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
             .maxDelayBetweenTwoTransactions,
           this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
             .minDelayBetweenTwoTransactions
         ) * 1000;
-      logger.info(
-        `${this.logPrefix(connectorId)} waiting for ${Utils.formatDurationMilliSeconds(wait)}`
-      );
-      await Utils.sleep(wait);
-      const start = Utils.secureRandom();
+      logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`);
+      await sleep(wait);
+      const start = secureRandom();
       if (
         start <
         this.chargingStation.getAutomaticTransactionGeneratorConfiguration().probabilityOfStart
@@ -260,18 +268,18 @@ export class AutomaticTransactionGenerator extends AsyncResource {
         if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
           // Wait until end of transaction
           const waitTrxEnd =
-            Utils.getRandomInteger(
+            getRandomInteger(
               this.chargingStation.getAutomaticTransactionGeneratorConfiguration().maxDuration,
               this.chargingStation.getAutomaticTransactionGeneratorConfiguration().minDuration
             ) * 1000;
           logger.info(
             `${this.logPrefix(connectorId)} transaction started with id ${this.chargingStation
               .getConnectorStatus(connectorId)
-              ?.transactionId?.toString()} and will stop in ${Utils.formatDurationMilliSeconds(
+              ?.transactionId?.toString()} and will stop in ${formatDurationMilliSeconds(
               waitTrxEnd
             )}`
           );
-          await Utils.sleep(waitTrxEnd);
+          await sleep(waitTrxEnd);
           // Stop transaction
           logger.info(
             `${this.logPrefix(connectorId)} stop transaction with id ${this.chargingStation
@@ -297,7 +305,7 @@ export class AutomaticTransactionGenerator extends AsyncResource {
     logger.info(
       `${this.logPrefix(
         connectorId
-      )} stopped on connector and lasted for ${Utils.formatDurationMilliSeconds(
+      )} stopped on connector and lasted for ${formatDurationMilliSeconds(
         this.connectorsStatus.get(connectorId).stoppedDate.getTime() -
           this.connectorsStatus.get(connectorId).startDate.getTime()
       )}`
@@ -346,7 +354,7 @@ export class AutomaticTransactionGenerator extends AsyncResource {
   }
 
   private getConnectorStatus(connectorId: number): Status {
-    const connectorStatus = Utils.cloneObject(
+    const connectorStatus = cloneObject(
       this.chargingStation.getAutomaticTransactionGeneratorStatuses()
     )[connectorId];
     delete connectorStatus?.startDate;
@@ -458,7 +466,7 @@ export class AutomaticTransactionGenerator extends AsyncResource {
       const transactionId = this.chargingStation.getConnectorStatus(connectorId)?.transactionId;
       logger.warn(
         `${this.logPrefix(connectorId)} stopping a not started transaction${
-          !Utils.isNullOrUndefined(transactionId) ? ` with id ${transactionId?.toString()}` : ''
+          !isNullOrUndefined(transactionId) ? ` with id ${transactionId?.toString()}` : ''
         }`
       );
     }
@@ -473,9 +481,9 @@ export class AutomaticTransactionGenerator extends AsyncResource {
   }
 
   private logPrefix = (connectorId?: number): string => {
-    return Utils.logPrefix(
+    return logPrefix(
       ` ${this.chargingStation.stationInfo.chargingStationId} | ATG${
-        !Utils.isNullOrUndefined(connectorId) ? ` on connector #${connectorId.toString()}` : ''
+        !isNullOrUndefined(connectorId) ? ` on connector #${connectorId.toString()}` : ''
       }:`
     );
   };
index 8a3f9078d92ccafcdaf8013e71c5502b17d4c1a0..cb4b65ebab581860c0ae39ea83493df9785e4ee6 100644 (file)
@@ -26,9 +26,13 @@ import {
 import {
   Configuration,
   Constants,
-  Utils,
+  formatDurationMilliSeconds,
+  generateUUID,
   handleUncaughtException,
   handleUnhandledRejection,
+  isNotEmptyArray,
+  isNullOrUndefined,
+  logPrefix,
   logger,
 } from '../utils';
 import { type WorkerAbstract, WorkerFactory } from '../worker';
@@ -132,7 +136,7 @@ export class Bootstrap extends EventEmitter {
                 ? `/${Configuration.getWorker().poolMaxSize?.toString()}`
                 : ''
             } worker(s) concurrently running in '${Configuration.getWorker().processType}' mode${
-              !Utils.isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker)
+              !isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker)
                 ? ` (${this.workerImplementation?.maxElementsPerWorker} charging station(s) per worker)`
                 : ''
             }`
@@ -158,7 +162,7 @@ export class Bootstrap extends EventEmitter {
         this.stopping = true;
         await this.uiServer?.sendInternalRequest(
           this.uiServer.buildProtocolRequest(
-            Utils.generateUUID(),
+            generateUUID(),
             ProcedureName.STOP_CHARGING_STATION,
             Constants.EMPTY_FREEZED_OBJECT
           )
@@ -171,7 +175,7 @@ export class Bootstrap extends EventEmitter {
           ),
           new Promise<string>((resolve) => {
             setTimeout(() => {
-              const message = `Timeout reached ${Utils.formatDurationMilliSeconds(
+              const message = `Timeout reached ${formatDurationMilliSeconds(
                 Constants.STOP_SIMULATOR_TIMEOUT
               )} at stopping charging stations simulator`;
               console.warn(chalk.yellow(message));
@@ -301,7 +305,7 @@ export class Bootstrap extends EventEmitter {
     if (this.initializedCounters === false) {
       this.resetCounters();
       const stationTemplateUrls = Configuration.getStationTemplateUrls();
-      if (Utils.isNotEmptyArray(stationTemplateUrls)) {
+      if (isNotEmptyArray(stationTemplateUrls)) {
         this.numberOfChargingStationTemplates = stationTemplateUrls.length;
         for (const stationTemplateUrl of stationTemplateUrls) {
           this.numberOfChargingStations += stationTemplateUrl.numberOfStations ?? 0;
@@ -356,6 +360,6 @@ export class Bootstrap extends EventEmitter {
   };
 
   private logPrefix = (): string => {
-    return Utils.logPrefix(' Bootstrap |');
+    return logPrefix(' Bootstrap |');
   };
 }
index fd9745563f4f21aa055e6ebabe5d50030c8b42d7..af021085a73a31b157dada6c2604ad81ba3644ea 100644 (file)
@@ -100,15 +100,30 @@ import {
   Configuration,
   Constants,
   DCElectricUtils,
-  Utils,
   buildChargingStationAutomaticTransactionGeneratorConfiguration,
   buildConnectorsStatus,
   buildEvsesStatus,
   buildStartedMessage,
   buildStoppedMessage,
   buildUpdatedMessage,
+  cloneObject,
+  convertToBoolean,
+  convertToInt,
+  exponentialDelay,
+  formatDurationMilliSeconds,
+  formatDurationSeconds,
+  getRandomInteger,
+  getWebSocketCloseEventStatusString,
   handleFileException,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isUndefined,
+  logPrefix,
   logger,
+  roundTo,
+  secureRandom,
+  sleep,
   watchJsonFile,
 } from '../utils';
 
@@ -175,8 +190,8 @@ export class ChargingStation {
     return new URL(
       `${
         this.getSupervisionUrlOcppConfiguration() &&
-        Utils.isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
-        Utils.isNotEmptyString(
+        isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
+        isNotEmptyString(
           ChargingStationConfigurationUtils.getConfigurationKey(
             this,
             this.getSupervisionUrlOcppKey()
@@ -192,9 +207,9 @@ export class ChargingStation {
   }
 
   public logPrefix = (): string => {
-    return Utils.logPrefix(
+    return logPrefix(
       ` ${
-        (Utils.isNotEmptyString(this?.stationInfo?.chargingStationId)
+        (isNotEmptyString(this?.stationInfo?.chargingStationId)
           ? this?.stationInfo?.chargingStationId
           : ChargingStationUtils.getChargingStationId(this.index, this.getTemplateFromFile())) ??
         'Error at building log prefix'
@@ -203,7 +218,7 @@ export class ChargingStation {
   };
 
   public hasIdTags(): boolean {
-    return Utils.isNotEmptyArray(
+    return isNotEmptyArray(
       this.idTagsCache.getIdTags(ChargingStationUtils.getIdTagsFile(this.stationInfo))
     );
   }
@@ -224,9 +239,7 @@ export class ChargingStation {
     const localStationInfo: ChargingStationInfo = stationInfo ?? this.stationInfo;
     switch (this.getCurrentOutType(stationInfo)) {
       case CurrentType.AC:
-        return !Utils.isUndefined(localStationInfo.numberOfPhases)
-          ? localStationInfo.numberOfPhases
-          : 3;
+        return !isUndefined(localStationInfo.numberOfPhases) ? localStationInfo.numberOfPhases : 3;
       case CurrentType.DC:
         return 0;
     }
@@ -241,7 +254,7 @@ export class ChargingStation {
   }
 
   public inUnknownState(): boolean {
-    return Utils.isNullOrUndefined(this?.bootNotificationResponse?.status);
+    return isNullOrUndefined(this?.bootNotificationResponse?.status);
   }
 
   public inPendingState(): boolean {
@@ -340,7 +353,7 @@ export class ChargingStation {
   public getConnectorMaximumAvailablePower(connectorId: number): number {
     let connectorAmperageLimitationPowerLimit: number;
     if (
-      !Utils.isNullOrUndefined(this.getAmperageLimitation()) &&
+      !isNullOrUndefined(this.getAmperageLimitation()) &&
       this.getAmperageLimitation() < this.stationInfo?.maximumAmperage
     ) {
       connectorAmperageLimitationPowerLimit =
@@ -472,9 +485,7 @@ export class ChargingStation {
       this,
       StandardParametersKey.AuthorizeRemoteTxRequests
     );
-    return authorizeRemoteTxRequests
-      ? Utils.convertToBoolean(authorizeRemoteTxRequests.value)
-      : false;
+    return authorizeRemoteTxRequests ? convertToBoolean(authorizeRemoteTxRequests.value) : false;
   }
 
   public getLocalAuthListEnabled(): boolean {
@@ -482,7 +493,7 @@ export class ChargingStation {
       this,
       StandardParametersKey.LocalAuthListEnabled
     );
-    return localAuthListEnabled ? Utils.convertToBoolean(localAuthListEnabled.value) : false;
+    return localAuthListEnabled ? convertToBoolean(localAuthListEnabled.value) : false;
   }
 
   public getHeartbeatInterval(): number {
@@ -491,14 +502,14 @@ export class ChargingStation {
       StandardParametersKey.HeartbeatInterval
     );
     if (HeartbeatInterval) {
-      return Utils.convertToInt(HeartbeatInterval.value) * 1000;
+      return convertToInt(HeartbeatInterval.value) * 1000;
     }
     const HeartBeatInterval = ChargingStationConfigurationUtils.getConfigurationKey(
       this,
       StandardParametersKey.HeartBeatInterval
     );
     if (HeartBeatInterval) {
-      return Utils.convertToInt(HeartBeatInterval.value) * 1000;
+      return convertToInt(HeartBeatInterval.value) * 1000;
     }
     this.stationInfo?.autoRegister === false &&
       logger.warn(
@@ -512,7 +523,7 @@ export class ChargingStation {
   public setSupervisionUrl(url: string): void {
     if (
       this.getSupervisionUrlOcppConfiguration() &&
-      Utils.isNotEmptyString(this.getSupervisionUrlOcppKey())
+      isNotEmptyString(this.getSupervisionUrlOcppKey())
     ) {
       ChargingStationConfigurationUtils.setConfigurationKeyValue(
         this,
@@ -539,13 +550,13 @@ export class ChargingStation {
           });
       }, this.getHeartbeatInterval());
       logger.info(
-        `${this.logPrefix()} Heartbeat started every ${Utils.formatDurationMilliSeconds(
+        `${this.logPrefix()} Heartbeat started every ${formatDurationMilliSeconds(
           this.getHeartbeatInterval()
         )}`
       );
     } else if (this.heartbeatSetInterval) {
       logger.info(
-        `${this.logPrefix()} Heartbeat already started every ${Utils.formatDurationMilliSeconds(
+        `${this.logPrefix()} Heartbeat already started every ${formatDurationMilliSeconds(
           this.getHeartbeatInterval()
         )}`
       );
@@ -593,7 +604,7 @@ export class ChargingStation {
       return;
     } else if (
       this.getConnectorStatus(connectorId)?.transactionStarted === true &&
-      Utils.isNullOrUndefined(this.getConnectorStatus(connectorId)?.transactionId)
+      isNullOrUndefined(this.getConnectorStatus(connectorId)?.transactionId)
     ) {
       logger.error(
         `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}
@@ -660,7 +671,7 @@ export class ChargingStation {
           this.logPrefix(),
           undefined,
           (event, filename): void => {
-            if (Utils.isNotEmptyString(filename) && event === 'change') {
+            if (isNotEmptyString(filename) && event === 'change') {
               try {
                 logger.debug(
                   `${this.logPrefix()} ${FileType.ChargingStationTemplate} ${
@@ -729,7 +740,7 @@ export class ChargingStation {
 
   public async reset(reason?: StopTransactionReason): Promise<void> {
     await this.stop(reason);
-    await Utils.sleep(this.stationInfo.resetTime);
+    await sleep(this.stationInfo.resetTime);
     this.initialize();
     this.start();
   }
@@ -768,8 +779,8 @@ export class ChargingStation {
       return;
     }
     if (
-      !Utils.isNullOrUndefined(this.stationInfo.supervisionUser) &&
-      !Utils.isNullOrUndefined(this.stationInfo.supervisionPassword)
+      !isNullOrUndefined(this.stationInfo.supervisionUser) &&
+      !isNullOrUndefined(this.stationInfo.supervisionPassword)
     ) {
       options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`;
     }
@@ -858,7 +869,7 @@ export class ChargingStation {
 
   public startAutomaticTransactionGenerator(connectorIds?: number[]): void {
     this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this);
-    if (Utils.isNotEmptyArray(connectorIds)) {
+    if (isNotEmptyArray(connectorIds)) {
       for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.startConnector(connectorId);
       }
@@ -870,7 +881,7 @@ export class ChargingStation {
   }
 
   public stopAutomaticTransactionGenerator(connectorIds?: number[]): void {
-    if (Utils.isNotEmptyArray(connectorIds)) {
+    if (isNotEmptyArray(connectorIds)) {
       for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.stopConnector(connectorId);
       }
@@ -919,7 +930,7 @@ export class ChargingStation {
   }
 
   public getReservationOnConnectorId0Enabled(): boolean {
-    return Utils.convertToBoolean(
+    return convertToBoolean(
       ChargingStationConfigurationUtils.getConfigurationKey(
         this,
         StandardParametersKey.ReserveConnectorZeroSupported
@@ -997,7 +1008,7 @@ export class ChargingStation {
       ReservationFilterKey.RESERVATION_ID,
       reservation?.id
     );
-    return Utils.isUndefined(foundReservation) ? [false, null] : [true, foundReservation];
+    return isUndefined(foundReservation) ? [false, null] : [true, foundReservation];
   }
 
   public startReservationExpirationSetInterval(customInterval?: number): void {
@@ -1052,12 +1063,12 @@ export class ChargingStation {
     if (alreadyExists) {
       return alreadyExists;
     }
-    const userReservedAlready = Utils.isUndefined(
+    const userReservedAlready = isUndefined(
       this.getReservationBy(ReservationFilterKey.ID_TAG, idTag)
     )
       ? false
       : true;
-    const notConnectorZero = Utils.isUndefined(connectorId) ? true : connectorId > 0;
+    const notConnectorZero = isUndefined(connectorId) ? true : connectorId > 0;
     const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0;
     return !alreadyExists && !userReservedAlready && notConnectorZero && freeConnectorsAvailable;
   }
@@ -1174,9 +1185,9 @@ export class ChargingStation {
     );
     stationInfo.ocppVersion = stationTemplate?.ocppVersion ?? OCPPVersion.VERSION_16;
     ChargingStationUtils.createSerialNumber(stationTemplate, stationInfo);
-    if (Utils.isNotEmptyArray(stationTemplate?.power)) {
+    if (isNotEmptyArray(stationTemplate?.power)) {
       stationTemplate.power = stationTemplate.power as number[];
-      const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationTemplate.power.length);
+      const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length);
       stationInfo.maximumPower =
         stationTemplate?.powerUnit === PowerUnits.KILO_WATT
           ? stationTemplate.power[powerArrayRandomIndex] * 1000
@@ -1191,7 +1202,7 @@ export class ChargingStation {
     stationInfo.firmwareVersionPattern =
       stationTemplate?.firmwareVersionPattern ?? Constants.SEMVER_PATTERN;
     if (
-      Utils.isNotEmptyString(stationInfo.firmwareVersion) &&
+      isNotEmptyString(stationInfo.firmwareVersion) &&
       new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion) === false
     ) {
       logger.warn(
@@ -1209,7 +1220,7 @@ export class ChargingStation {
       },
       stationTemplate?.firmwareUpgrade ?? {}
     );
-    stationInfo.resetTime = !Utils.isNullOrUndefined(stationTemplate?.resetTime)
+    stationInfo.resetTime = !isNullOrUndefined(stationTemplate?.resetTime)
       ? stationTemplate.resetTime * 1000
       : Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
     stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo);
@@ -1289,8 +1300,8 @@ export class ChargingStation {
     this.stationInfo = this.getStationInfo();
     if (
       this.stationInfo.firmwareStatus === FirmwareStatus.Installing &&
-      Utils.isNotEmptyString(this.stationInfo.firmwareVersion) &&
-      Utils.isNotEmptyString(this.stationInfo.firmwareVersionPattern)
+      isNotEmptyString(this.stationInfo.firmwareVersion) &&
+      isNotEmptyString(this.stationInfo.firmwareVersionPattern)
     ) {
       const patternGroup: number | undefined =
         this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
@@ -1300,7 +1311,7 @@ export class ChargingStation {
         ?.slice(1, patternGroup + 1);
       const patchLevelIndex = match.length - 1;
       match[patchLevelIndex] = (
-        Utils.convertToInt(match[patchLevelIndex]) +
+        convertToInt(match[patchLevelIndex]) +
         this.stationInfo.firmwareUpgrade?.versionUpgrade?.step
       ).toString();
       this.stationInfo.firmwareVersion = match?.join('.');
@@ -1383,7 +1394,7 @@ export class ChargingStation {
     }
     if (
       this.getSupervisionUrlOcppConfiguration() &&
-      Utils.isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
+      isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
       !ChargingStationConfigurationUtils.getConfigurationKey(this, this.getSupervisionUrlOcppKey())
     ) {
       ChargingStationConfigurationUtils.addConfigurationKey(
@@ -1394,7 +1405,7 @@ export class ChargingStation {
       );
     } else if (
       !this.getSupervisionUrlOcppConfiguration() &&
-      Utils.isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
+      isNotEmptyString(this.getSupervisionUrlOcppKey()) &&
       ChargingStationConfigurationUtils.getConfigurationKey(this, this.getSupervisionUrlOcppKey())
     ) {
       ChargingStationConfigurationUtils.deleteConfigurationKey(
@@ -1404,7 +1415,7 @@ export class ChargingStation {
       );
     }
     if (
-      Utils.isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+      isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
       !ChargingStationConfigurationUtils.getConfigurationKey(
         this,
         this.stationInfo.amperageLimitationOcppKey
@@ -1524,11 +1535,11 @@ export class ChargingStation {
   private initializeConnectorsOrEvsesFromFile(configuration: ChargingStationConfiguration): void {
     if (configuration?.connectorsStatus && !configuration?.evsesStatus) {
       for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) {
-        this.connectors.set(connectorId, Utils.cloneObject<ConnectorStatus>(connectorStatus));
+        this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
       }
     } else if (configuration?.evsesStatus && !configuration?.connectorsStatus) {
       for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) {
-        const evseStatus = Utils.cloneObject<EvseStatusConfiguration>(evseStatusConfiguration);
+        const evseStatus = cloneObject<EvseStatusConfiguration>(evseStatusConfiguration);
         delete evseStatus.connectorsStatus;
         this.evses.set(evseId, {
           ...(evseStatus as EvseStatus),
@@ -1608,7 +1619,7 @@ export class ChargingStation {
             }
             const templateConnectorId =
               connectorId > 0 && stationTemplate?.randomConnectors
-                ? Utils.getRandomInteger(templateMaxAvailableConnectors, 1)
+                ? getRandomInteger(templateMaxAvailableConnectors, 1)
                 : connectorId;
             const connectorStatus = stationTemplate?.Connectors[templateConnectorId];
             ChargingStationUtils.checkStationInfoConnectorStatus(
@@ -1617,7 +1628,7 @@ export class ChargingStation {
               this.logPrefix(),
               this.templateFile
             );
-            this.connectors.set(connectorId, Utils.cloneObject<ConnectorStatus>(connectorStatus));
+            this.connectors.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
           }
           ChargingStationUtils.initializeConnectorsMapStatus(this.connectors, this.logPrefix());
           this.saveConnectorsStatus();
@@ -1670,7 +1681,7 @@ export class ChargingStation {
         const templateMaxEvses = ChargingStationUtils.getMaxNumberOfEvses(stationTemplate?.Evses);
         if (templateMaxEvses > 0) {
           for (const evse in stationTemplate.Evses) {
-            const evseId = Utils.convertToInt(evse);
+            const evseId = convertToInt(evse);
             this.evses.set(evseId, {
               connectors: ChargingStationUtils.buildConnectorsMap(
                 stationTemplate?.Evses[evse]?.Connectors,
@@ -1704,7 +1715,7 @@ export class ChargingStation {
 
   private getConfigurationFromFile(): ChargingStationConfiguration | undefined {
     let configuration: ChargingStationConfiguration | undefined;
-    if (Utils.isNotEmptyString(this.configurationFile) && existsSync(this.configurationFile)) {
+    if (isNotEmptyString(this.configurationFile) && existsSync(this.configurationFile)) {
       try {
         if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
           configuration = this.sharedLRUCache.getChargingStationConfiguration(
@@ -1747,13 +1758,13 @@ export class ChargingStation {
   }
 
   private saveConfiguration(): void {
-    if (Utils.isNotEmptyString(this.configurationFile)) {
+    if (isNotEmptyString(this.configurationFile)) {
       try {
         if (!existsSync(dirname(this.configurationFile))) {
           mkdirSync(dirname(this.configurationFile), { recursive: true });
         }
         let configurationData: ChargingStationConfiguration =
-          Utils.cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()) ?? {};
+          cloneObject<ChargingStationConfiguration>(this.getConfigurationFromFile()) ?? {};
         if (this.getStationInfoPersistentConfiguration() && this.stationInfo) {
           configurationData.stationInfo = this.stationInfo;
         } else {
@@ -1879,7 +1890,7 @@ export class ChargingStation {
           });
           if (this.isRegistered() === false) {
             this.getRegistrationMaxRetries() !== -1 && ++registrationRetryCount;
-            await Utils.sleep(
+            await sleep(
               this?.bootNotificationResponse?.interval
                 ? this.bootNotificationResponse.interval * 1000
                 : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
@@ -1916,7 +1927,7 @@ export class ChargingStation {
       case WebSocketCloseEventStatusCode.CLOSE_NORMAL:
       case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS:
         logger.info(
-          `${this.logPrefix()} WebSocket normally closed with status '${Utils.getWebSocketCloseEventStatusString(
+          `${this.logPrefix()} WebSocket normally closed with status '${getWebSocketCloseEventStatusString(
             code
           )}' and reason '${reason.toString()}'`
         );
@@ -1925,7 +1936,7 @@ export class ChargingStation {
       // Abnormal close
       default:
         logger.error(
-          `${this.logPrefix()} WebSocket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString(
+          `${this.logPrefix()} WebSocket abnormally closed with status '${getWebSocketCloseEventStatusString(
             code
           )}' and reason '${reason.toString()}'`
         );
@@ -2201,14 +2212,14 @@ export class ChargingStation {
 
   private getAmperageLimitation(): number | undefined {
     if (
-      Utils.isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+      isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
       ChargingStationConfigurationUtils.getConfigurationKey(
         this,
         this.stationInfo.amperageLimitationOcppKey
       )
     ) {
       return (
-        Utils.convertToInt(
+        convertToInt(
           ChargingStationConfigurationUtils.getConfigurationKey(
             this,
             this.stationInfo.amperageLimitationOcppKey
@@ -2339,7 +2350,7 @@ export class ChargingStation {
       this,
       StandardParametersKey.WebSocketPingInterval
     )
-      ? Utils.convertToInt(
+      ? convertToInt(
           ChargingStationConfigurationUtils.getConfigurationKey(
             this,
             StandardParametersKey.WebSocketPingInterval
@@ -2353,13 +2364,13 @@ export class ChargingStation {
         }
       }, webSocketPingInterval * 1000);
       logger.info(
-        `${this.logPrefix()} WebSocket ping started every ${Utils.formatDurationSeconds(
+        `${this.logPrefix()} WebSocket ping started every ${formatDurationSeconds(
           webSocketPingInterval
         )}`
       );
     } else if (this.webSocketPingSetInterval) {
       logger.info(
-        `${this.logPrefix()} WebSocket ping already started every ${Utils.formatDurationSeconds(
+        `${this.logPrefix()} WebSocket ping already started every ${formatDurationSeconds(
           webSocketPingInterval
         )}`
       );
@@ -2380,11 +2391,11 @@ export class ChargingStation {
   private getConfiguredSupervisionUrl(): URL {
     let configuredSupervisionUrl: string;
     const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls();
-    if (Utils.isNotEmptyArray(supervisionUrls)) {
+    if (isNotEmptyArray(supervisionUrls)) {
       let configuredSupervisionUrlIndex: number;
       switch (Configuration.getSupervisionUrlDistribution()) {
         case SupervisionUrlDistribution.RANDOM:
-          configuredSupervisionUrlIndex = Math.floor(Utils.secureRandom() * supervisionUrls.length);
+          configuredSupervisionUrlIndex = Math.floor(secureRandom() * supervisionUrls.length);
           break;
         case SupervisionUrlDistribution.ROUND_ROBIN:
         case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
@@ -2404,7 +2415,7 @@ export class ChargingStation {
     } else {
       configuredSupervisionUrl = supervisionUrls as string;
     }
-    if (Utils.isNotEmptyString(configuredSupervisionUrl)) {
+    if (isNotEmptyString(configuredSupervisionUrl)) {
       return new URL(configuredSupervisionUrl);
     }
     const errorMsg = 'No supervision url(s) configured';
@@ -2445,7 +2456,7 @@ export class ChargingStation {
     ) {
       ++this.autoReconnectRetryCount;
       const reconnectDelay = this.getReconnectExponentialDelay()
-        ? Utils.exponentialDelay(this.autoReconnectRetryCount)
+        ? exponentialDelay(this.autoReconnectRetryCount)
         : this.getConnectionTimeout() * 1000;
       const reconnectDelayWithdraw = 1000;
       const reconnectTimeout =
@@ -2453,12 +2464,12 @@ export class ChargingStation {
           ? reconnectDelay - reconnectDelayWithdraw
           : 0;
       logger.error(
-        `${this.logPrefix()} WebSocket connection retry in ${Utils.roundTo(
+        `${this.logPrefix()} WebSocket connection retry in ${roundTo(
           reconnectDelay,
           2
         )}ms, timeout ${reconnectTimeout}ms`
       );
-      await Utils.sleep(reconnectDelay);
+      await sleep(reconnectDelay);
       logger.error(
         `${this.logPrefix()} WebSocket connection retry #${this.autoReconnectRetryCount.toString()}`
       );
index ab781fae3cb3382022abb8f61ed7b55f021e9ef0..3e5d658d37376e3409bd0bbe386e4a88c9ae5bc5 100644 (file)
@@ -31,7 +31,21 @@ import {
   RecurrencyKindType,
   Voltage,
 } from '../types';
-import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../utils';
+import {
+  ACElectricUtils,
+  Constants,
+  DCElectricUtils,
+  cloneObject,
+  convertToInt,
+  isEmptyObject,
+  isEmptyString,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isUndefined,
+  logger,
+  secureRandom,
+} from '../utils';
 
 const moduleName = 'ChargingStationUtils';
 
@@ -72,16 +86,16 @@ export class ChargingStationUtils {
     const chargingStationInfo = {
       chargePointModel: stationTemplate.chargePointModel,
       chargePointVendor: stationTemplate.chargePointVendor,
-      ...(!Utils.isUndefined(stationTemplate.chargeBoxSerialNumberPrefix) && {
+      ...(!isUndefined(stationTemplate.chargeBoxSerialNumberPrefix) && {
         chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix,
       }),
-      ...(!Utils.isUndefined(stationTemplate.chargePointSerialNumberPrefix) && {
+      ...(!isUndefined(stationTemplate.chargePointSerialNumberPrefix) && {
         chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix,
       }),
-      ...(!Utils.isUndefined(stationTemplate.meterSerialNumberPrefix) && {
+      ...(!isUndefined(stationTemplate.meterSerialNumberPrefix) && {
         meterSerialNumber: stationTemplate.meterSerialNumberPrefix,
       }),
-      ...(!Utils.isUndefined(stationTemplate.meterType) && {
+      ...(!isUndefined(stationTemplate.meterType) && {
         meterType: stationTemplate.meterType,
       }),
     };
@@ -164,17 +178,17 @@ export class ChargingStationUtils {
     logPrefix: string,
     templateFile: string
   ) {
-    if (Utils.isNullOrUndefined(stationTemplate)) {
+    if (isNullOrUndefined(stationTemplate)) {
       const errorMsg = `Failed to read charging station template file ${templateFile}`;
       logger.error(`${logPrefix} ${errorMsg}`);
       throw new BaseError(errorMsg);
     }
-    if (Utils.isEmptyObject(stationTemplate)) {
+    if (isEmptyObject(stationTemplate)) {
       const errorMsg = `Empty charging station information from template file ${templateFile}`;
       logger.error(`${logPrefix} ${errorMsg}`);
       throw new BaseError(errorMsg);
     }
-    if (Utils.isEmptyObject(stationTemplate.AutomaticTransactionGenerator)) {
+    if (isEmptyObject(stationTemplate.AutomaticTransactionGenerator)) {
       stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION;
       logger.warn(
         `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default: %j`,
@@ -182,8 +196,8 @@ export class ChargingStationUtils {
       );
     }
     if (
-      Utils.isNullOrUndefined(stationTemplate.idTagsFile) ||
-      Utils.isEmptyString(stationTemplate.idTagsFile)
+      isNullOrUndefined(stationTemplate.idTagsFile) ||
+      isEmptyString(stationTemplate.idTagsFile)
     ) {
       logger.warn(
         `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`
@@ -232,7 +246,7 @@ export class ChargingStationUtils {
     logPrefix: string,
     templateFile: string
   ): void {
-    if (!Utils.isNullOrUndefined(connectorStatus?.status)) {
+    if (!isNullOrUndefined(connectorStatus?.status)) {
       logger.warn(
         `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId} status configuration defined, undefine it`
       );
@@ -249,14 +263,14 @@ export class ChargingStationUtils {
     if (ChargingStationUtils.getMaxNumberOfConnectors(connectors) > 0) {
       for (const connector in connectors) {
         const connectorStatus = connectors[connector];
-        const connectorId = Utils.convertToInt(connector);
+        const connectorId = convertToInt(connector);
         ChargingStationUtils.checkStationInfoConnectorStatus(
           connectorId,
           connectorStatus,
           logPrefix,
           templateFile
         );
-        connectorsMap.set(connectorId, Utils.cloneObject<ConnectorStatus>(connectorStatus));
+        connectorsMap.set(connectorId, cloneObject<ConnectorStatus>(connectorStatus));
       }
     } else {
       logger.warn(
@@ -280,12 +294,12 @@ export class ChargingStationUtils {
       }
       if (connectorId === 0) {
         connectors.get(connectorId).availability = AvailabilityType.Operative;
-        if (Utils.isUndefined(connectors.get(connectorId)?.chargingProfiles)) {
+        if (isUndefined(connectors.get(connectorId)?.chargingProfiles)) {
           connectors.get(connectorId).chargingProfiles = [];
         }
       } else if (
         connectorId > 0 &&
-        Utils.isNullOrUndefined(connectors.get(connectorId)?.transactionStarted)
+        isNullOrUndefined(connectors.get(connectorId)?.transactionStarted)
       ) {
         ChargingStationUtils.initializeConnectorStatus(connectors.get(connectorId));
       }
@@ -315,21 +329,21 @@ export class ChargingStationUtils {
         return {
           chargePointModel: stationInfo.chargePointModel,
           chargePointVendor: stationInfo.chargePointVendor,
-          ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumber) && {
+          ...(!isUndefined(stationInfo.chargeBoxSerialNumber) && {
             chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
           }),
-          ...(!Utils.isUndefined(stationInfo.chargePointSerialNumber) && {
+          ...(!isUndefined(stationInfo.chargePointSerialNumber) && {
             chargePointSerialNumber: stationInfo.chargePointSerialNumber,
           }),
-          ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
+          ...(!isUndefined(stationInfo.firmwareVersion) && {
             firmwareVersion: stationInfo.firmwareVersion,
           }),
-          ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
-          ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
-          ...(!Utils.isUndefined(stationInfo.meterSerialNumber) && {
+          ...(!isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
+          ...(!isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
+          ...(!isUndefined(stationInfo.meterSerialNumber) && {
             meterSerialNumber: stationInfo.meterSerialNumber,
           }),
-          ...(!Utils.isUndefined(stationInfo.meterType) && {
+          ...(!isUndefined(stationInfo.meterType) && {
             meterType: stationInfo.meterType,
           }),
         } as OCPP16BootNotificationRequest;
@@ -340,16 +354,16 @@ export class ChargingStationUtils {
           chargingStation: {
             model: stationInfo.chargePointModel,
             vendorName: stationInfo.chargePointVendor,
-            ...(!Utils.isUndefined(stationInfo.firmwareVersion) && {
+            ...(!isUndefined(stationInfo.firmwareVersion) && {
               firmwareVersion: stationInfo.firmwareVersion,
             }),
-            ...(!Utils.isUndefined(stationInfo.chargeBoxSerialNumber) && {
+            ...(!isUndefined(stationInfo.chargeBoxSerialNumber) && {
               serialNumber: stationInfo.chargeBoxSerialNumber,
             }),
-            ...((!Utils.isUndefined(stationInfo.iccid) || !Utils.isUndefined(stationInfo.imsi)) && {
+            ...((!isUndefined(stationInfo.iccid) || !isUndefined(stationInfo.imsi)) && {
               modem: {
-                ...(!Utils.isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
-                ...(!Utils.isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
+                ...(!isUndefined(stationInfo.iccid) && { iccid: stationInfo.iccid }),
+                ...(!isUndefined(stationInfo.imsi) && { imsi: stationInfo.imsi }),
               },
             }),
           },
@@ -385,7 +399,7 @@ export class ChargingStationUtils {
   public static stationTemplateToStationInfo(
     stationTemplate: ChargingStationTemplate
   ): ChargingStationInfo {
-    stationTemplate = Utils.cloneObject<ChargingStationTemplate>(stationTemplate);
+    stationTemplate = cloneObject<ChargingStationTemplate>(stationTemplate);
     delete stationTemplate.power;
     delete stationTemplate.powerUnit;
     delete stationTemplate?.Connectors;
@@ -415,11 +429,11 @@ export class ChargingStationUtils {
           upperCase: params.randomSerialNumberUpperCase,
         })
       : '';
-    Utils.isNotEmptyString(stationTemplate?.chargePointSerialNumberPrefix) &&
+    isNotEmptyString(stationTemplate?.chargePointSerialNumberPrefix) &&
       (stationInfo.chargePointSerialNumber = `${stationTemplate.chargePointSerialNumberPrefix}${serialNumberSuffix}`);
-    Utils.isNotEmptyString(stationTemplate?.chargeBoxSerialNumberPrefix) &&
+    isNotEmptyString(stationTemplate?.chargeBoxSerialNumberPrefix) &&
       (stationInfo.chargeBoxSerialNumber = `${stationTemplate.chargeBoxSerialNumberPrefix}${serialNumberSuffix}`);
-    Utils.isNotEmptyString(stationTemplate?.meterSerialNumberPrefix) &&
+    isNotEmptyString(stationTemplate?.meterSerialNumberPrefix) &&
       (stationInfo.meterSerialNumber = `${stationTemplate.meterSerialNumberPrefix}${serialNumberSuffix}`);
   }
 
@@ -467,23 +481,23 @@ export class ChargingStationUtils {
     let limit: number, matchingChargingProfile: ChargingProfile;
     // Get charging profiles for connector and sort by stack level
     const chargingProfiles =
-      Utils.cloneObject<ChargingProfile[]>(
+      cloneObject<ChargingProfile[]>(
         chargingStation.getConnectorStatus(connectorId)?.chargingProfiles
       )?.sort((a, b) => b.stackLevel - a.stackLevel) ?? [];
     // Get profiles on connector 0
     if (chargingStation.getConnectorStatus(0)?.chargingProfiles) {
       chargingProfiles.push(
-        ...Utils.cloneObject<ChargingProfile[]>(
+        ...cloneObject<ChargingProfile[]>(
           chargingStation.getConnectorStatus(0).chargingProfiles
         ).sort((a, b) => b.stackLevel - a.stackLevel)
       );
     }
-    if (Utils.isNotEmptyArray(chargingProfiles)) {
+    if (isNotEmptyArray(chargingProfiles)) {
       const result = ChargingStationUtils.getLimitFromChargingProfiles(
         chargingProfiles,
         chargingStation.logPrefix()
       );
-      if (!Utils.isNullOrUndefined(result)) {
+      if (!isNullOrUndefined(result)) {
         limit = result?.limit;
         matchingChargingProfile = result?.matchingChargingProfile;
         switch (chargingStation.getCurrentOutType()) {
@@ -570,11 +584,11 @@ export class ChargingStationUtils {
 
   private static getConfiguredNumberOfConnectors(stationTemplate: ChargingStationTemplate): number {
     let configuredMaxConnectors: number;
-    if (Utils.isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
+    if (isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
       const numberOfConnectors = stationTemplate.numberOfConnectors as number[];
       configuredMaxConnectors =
-        numberOfConnectors[Math.floor(Utils.secureRandom() * numberOfConnectors.length)];
-    } else if (Utils.isUndefined(stationTemplate.numberOfConnectors) === false) {
+        numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)];
+    } else if (isUndefined(stationTemplate.numberOfConnectors) === false) {
       configuredMaxConnectors = stationTemplate.numberOfConnectors as number;
     } else if (stationTemplate.Connectors && !stationTemplate.Evses) {
       configuredMaxConnectors = stationTemplate?.Connectors[0]
@@ -630,7 +644,7 @@ export class ChargingStationUtils {
     connectorStatus.transactionStarted = false;
     connectorStatus.energyActiveImportRegisterValue = 0;
     connectorStatus.transactionEnergyActiveImportRegisterValue = 0;
-    if (Utils.isUndefined(connectorStatus.chargingProfiles)) {
+    if (isUndefined(connectorStatus.chargingProfiles)) {
       connectorStatus.chargingProfiles = [];
     }
   }
@@ -642,9 +656,9 @@ export class ChargingStationUtils {
     templateFile: string,
     logMsgToAppend = ''
   ): void {
-    if (!Utils.isUndefined(template[key])) {
+    if (!isUndefined(template[key])) {
       const logMsg = `Deprecated template key '${key}' usage in file '${templateFile}'${
-        Utils.isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
+        isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
       }`;
       logger.warn(`${logPrefix} ${logMsg}`);
       console.warn(chalk.yellow(`${logMsg}`));
@@ -656,7 +670,7 @@ export class ChargingStationUtils {
     deprecatedKey: string,
     key: string
   ): void {
-    if (!Utils.isUndefined(template[deprecatedKey])) {
+    if (!isUndefined(template[deprecatedKey])) {
       template[key] = template[deprecatedKey] as unknown;
       delete template[deprecatedKey];
     }
index c0f4d2b9b1e655c80b8280eb60e92b29ffa17688..0b3ba285dd080777ca60de657fe2060555553536 100644 (file)
@@ -3,7 +3,14 @@ import { type FSWatcher, readFileSync } from 'node:fs';
 import type { ChargingStation } from './ChargingStation';
 import { ChargingStationUtils } from './ChargingStationUtils';
 import { FileType, IdTagDistribution } from '../types';
-import { Utils, handleFileException, logger, watchJsonFile } from '../utils';
+import {
+  handleFileException,
+  isNotEmptyString,
+  logPrefix,
+  logger,
+  secureRandom,
+  watchJsonFile,
+} from '../utils';
 
 type IdTagsCacheValueType = {
   idTags: string[];
@@ -78,7 +85,7 @@ export class IdTagsCache {
     const addressableKey = this.getIdTagsCacheIndexesAddressableKey(file, hashId);
     this.idTagsCachesAddressableIndexes.set(
       addressableKey,
-      Math.floor(Utils.secureRandom() * idTags.length)
+      Math.floor(secureRandom() * idTags.length)
     );
     return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)];
   }
@@ -122,7 +129,7 @@ export class IdTagsCache {
         this.logPrefix(file),
         undefined,
         (event, filename) => {
-          if (Utils.isNotEmptyString(filename) && event === 'change') {
+          if (isNotEmptyString(filename) && event === 'change') {
             try {
               logger.debug(
                 `${this.logPrefix(file)} ${FileType.Authorization} file have changed, reload`
@@ -170,7 +177,7 @@ export class IdTagsCache {
   }
 
   private getIdTagsFromFile(file: string): string[] {
-    if (Utils.isNotEmptyString(file)) {
+    if (isNotEmptyString(file)) {
       try {
         return JSON.parse(readFileSync(file, 'utf8')) as string[];
       } catch (error) {
@@ -186,6 +193,6 @@ export class IdTagsCache {
   }
 
   private logPrefix = (file: string): string => {
-    return Utils.logPrefix(` Id tags cache for id tags file '${file}' |`);
+    return logPrefix(` Id tags cache for id tags file '${file}' |`);
   };
 }
index ba0a47d59b70962ab75517aab0215dda6b0b3424..57845313c8e39d64ae30aa632a1efea66ec6b765 100644 (file)
@@ -2,7 +2,7 @@ import LRUCache from 'mnemonist/lru-map-with-delete.js';
 
 import { Bootstrap } from './Bootstrap';
 import type { ChargingStationConfiguration, ChargingStationTemplate } from '../types';
-import { Utils } from '../utils';
+import { isEmptyObject, isNotEmptyArray, isNotEmptyString, isNullOrUndefined } from '../utils';
 
 enum CacheType {
   chargingStationTemplate = 'chargingStationTemplate',
@@ -109,15 +109,14 @@ export class SharedLRUCache {
     chargingStationConfiguration: ChargingStationConfiguration
   ): boolean {
     return (
-      Utils.isNullOrUndefined(chargingStationConfiguration?.configurationKey) === false &&
-      Utils.isNullOrUndefined(chargingStationConfiguration?.stationInfo) === false &&
-      Utils.isNullOrUndefined(chargingStationConfiguration?.automaticTransactionGenerator) ===
-        false &&
-      Utils.isNullOrUndefined(chargingStationConfiguration?.configurationHash) === false &&
-      Utils.isNotEmptyArray(chargingStationConfiguration?.configurationKey) === true &&
-      Utils.isEmptyObject(chargingStationConfiguration?.stationInfo) === false &&
-      Utils.isEmptyObject(chargingStationConfiguration?.automaticTransactionGenerator) === false &&
-      Utils.isNotEmptyString(chargingStationConfiguration?.configurationHash) === true
+      isNullOrUndefined(chargingStationConfiguration?.configurationKey) === false &&
+      isNullOrUndefined(chargingStationConfiguration?.stationInfo) === false &&
+      isNullOrUndefined(chargingStationConfiguration?.automaticTransactionGenerator) === false &&
+      isNullOrUndefined(chargingStationConfiguration?.configurationHash) === false &&
+      isNotEmptyArray(chargingStationConfiguration?.configurationKey) === true &&
+      isEmptyObject(chargingStationConfiguration?.stationInfo) === false &&
+      isEmptyObject(chargingStationConfiguration?.automaticTransactionGenerator) === false &&
+      isNotEmptyString(chargingStationConfiguration?.configurationHash) === true
     );
   }
 }
index b2828305625a3de2428cfedc23b150c2549511ff..9eb69cd3ebdf5fde8f2cbebbd0fc35445352228b 100644 (file)
@@ -34,7 +34,7 @@ import {
   type StopTransactionRequest,
   type StopTransactionResponse,
 } from '../../types';
-import { Constants, Utils, logger } from '../../utils';
+import { Constants, convertToInt, isEmptyObject, isNullOrUndefined, logger } from '../../utils';
 import type { ChargingStation } from '../ChargingStation';
 import { ChargingStationConfigurationUtils } from '../ChargingStationConfigurationUtils';
 import { OCPP16ServiceUtils } from '../ocpp';
@@ -196,7 +196,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
                   this.chargingStation.getConnectorStatus(requestPayload.connectorId)
                     ?.transactionId,
                   configuredMeterValueSampleInterval
-                    ? Utils.convertToInt(configuredMeterValueSampleInterval.value) * 1000
+                    ? convertToInt(configuredMeterValueSampleInterval.value) * 1000
                     : Constants.DEFAULT_METER_VALUES_INTERVAL
                 ),
               ],
@@ -256,12 +256,12 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
     }
     const [uuid, command, requestPayload] = validatedMessageEvent.data as BroadcastChannelRequest;
     if (
-      !Utils.isNullOrUndefined(requestPayload?.hashIds) &&
+      !isNullOrUndefined(requestPayload?.hashIds) &&
       requestPayload?.hashIds?.includes(this.chargingStation.stationInfo.hashId) === false
     ) {
       return;
     }
-    if (!Utils.isNullOrUndefined(requestPayload?.hashId)) {
+    if (!isNullOrUndefined(requestPayload?.hashId)) {
       logger.error(
         `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' array instead`
       );
@@ -271,10 +271,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
     let commandResponse: CommandResponse | void;
     try {
       commandResponse = await this.commandHandler(command, requestPayload);
-      if (
-        Utils.isNullOrUndefined(commandResponse) ||
-        Utils.isEmptyObject(commandResponse as CommandResponse)
-      ) {
+      if (isNullOrUndefined(commandResponse) || isEmptyObject(commandResponse as CommandResponse)) {
         responsePayload = {
           hashId: this.chargingStation.stationInfo.hashId,
           status: ResponseStatus.SUCCESS,
@@ -388,7 +385,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne
         return ResponseStatus.FAILURE;
       case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
       case BroadcastChannelProcedureName.METER_VALUES:
-        if (Utils.isEmptyObject(commandResponse) === true) {
+        if (isEmptyObject(commandResponse) === true) {
           return ResponseStatus.SUCCESS;
         }
         return ResponseStatus.FAILURE;
index b66cd8a09d21ca9179361c8232babe6e7f1c76c3..548b31472807c19b810007dde93e5319efd33643 100644 (file)
@@ -6,7 +6,7 @@ import {
   type ResponsePayload,
   ResponseStatus,
 } from '../../types';
-import { Utils, logger } from '../../utils';
+import { isNullOrUndefined, logger } from '../../utils';
 import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService';
 
 const moduleName = 'UIServiceWorkerBroadcastChannel';
@@ -70,7 +70,7 @@ export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
       status: responsesStatus,
       hashIdsSucceeded: this.responses
         .get(uuid)
-        ?.responses.filter(({ hashId }) => !Utils.isNullOrUndefined(hashId))
+        ?.responses.filter(({ hashId }) => !isNullOrUndefined(hashId))
         .map(({ status, hashId }) => {
           if (status === ResponseStatus.SUCCESS) {
             return hashId;
@@ -79,7 +79,7 @@ export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
       ...(responsesStatus === ResponseStatus.FAILURE && {
         hashIdsFailed: this.responses
           .get(uuid)
-          ?.responses.filter(({ hashId }) => !Utils.isNullOrUndefined(hashId))
+          ?.responses.filter(({ hashId }) => !isNullOrUndefined(hashId))
           .map(({ status, hashId }) => {
             if (status === ResponseStatus.FAILURE) {
               return hashId;
@@ -89,7 +89,7 @@ export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
       ...(responsesStatus === ResponseStatus.FAILURE && {
         responsesFailed: this.responses
           .get(uuid)
-          ?.responses.filter((response) => !Utils.isNullOrUndefined(response))
+          ?.responses.filter((response) => !isNullOrUndefined(response))
           .map((response) => {
             if (response.status === ResponseStatus.FAILURE) {
               return response;
index fd73b1bb59021ced8057ca4b85961dafbb860758..9168764dbe7a7dd3cfe1b689e7baa97fbb34ecc1 100644 (file)
@@ -6,7 +6,7 @@ import type {
   JsonType,
   MessageEvent,
 } from '../../types';
-import { Utils, logger } from '../../utils';
+import { logPrefix, logger, validateUUID } from '../../utils';
 
 const moduleName = 'WorkerBroadcastChannel';
 
@@ -41,7 +41,7 @@ export abstract class WorkerBroadcastChannel extends BroadcastChannel {
       );
       return false;
     }
-    if (Utils.validateUUID(messageEvent.data[0]) === false) {
+    if (validateUUID(messageEvent.data[0]) === false) {
       logger.error(
         `${this.logPrefix(
           moduleName,
@@ -54,6 +54,6 @@ export abstract class WorkerBroadcastChannel extends BroadcastChannel {
   }
 
   private logPrefix = (modName: string, methodName: string): string => {
-    return Utils.logPrefix(` Worker Broadcast Channel | ${modName}.${methodName}:`);
+    return logPrefix(` Worker Broadcast Channel | ${modName}.${methodName}:`);
   };
 }
index 73943d4e7f527fa11daf6512a4b7441fdb59081a..6e0b57be4570c808590f0df9232f4739a815e9a6 100644 (file)
@@ -87,7 +87,20 @@ import {
   type UnlockConnectorRequest,
   type UnlockConnectorResponse,
 } from '../../../types';
-import { Constants, Utils, logger } from '../../../utils';
+import {
+  Constants,
+  convertToDate,
+  convertToInt,
+  formatDurationMilliSeconds,
+  getRandomInteger,
+  isEmptyArray,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isUndefined,
+  logger,
+  sleep,
+} from '../../../utils';
 import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService';
 
 const moduleName = 'OCPP16IncomingRequestService';
@@ -412,7 +425,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       `${chargingStation.logPrefix()} ${
         commandPayload.type
       } reset command received, simulating it. The station will be
-        back online in ${Utils.formatDurationMilliSeconds(chargingStation.stationInfo.resetTime)}`
+        back online in ${formatDurationMilliSeconds(chargingStation.stationInfo.resetTime)}`
     );
     return OCPP16Constants.OCPP_RESPONSE_ACCEPTED;
   }
@@ -459,9 +472,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
   ): GetConfigurationResponse {
     const configurationKey: OCPPConfigurationKey[] = [];
     const unknownKey: string[] = [];
-    if (Utils.isUndefined(commandPayload.key) === true) {
+    if (isUndefined(commandPayload.key) === true) {
       for (const configuration of chargingStation.ocppConfiguration.configurationKey) {
-        if (Utils.isUndefined(configuration.visible) === true) {
+        if (isUndefined(configuration.visible) === true) {
           configuration.visible = true;
         }
         if (configuration.visible === false) {
@@ -473,7 +486,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
           value: configuration.value,
         });
       }
-    } else if (Utils.isNotEmptyArray(commandPayload.key) === true) {
+    } else if (isNotEmptyArray(commandPayload.key) === true) {
       for (const key of commandPayload.key) {
         const keyFound = ChargingStationConfigurationUtils.getConfigurationKey(
           chargingStation,
@@ -481,7 +494,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
           true
         );
         if (keyFound) {
-          if (Utils.isUndefined(keyFound.visible) === true) {
+          if (isUndefined(keyFound.visible) === true) {
             keyFound.visible = true;
           }
           if (keyFound.visible === false) {
@@ -632,9 +645,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       return OCPP16Constants.OCPP_RESPONSE_REJECTED;
     }
     if (
-      Utils.isEmptyArray(
-        chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles
-      )
+      isEmptyArray(chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles)
     ) {
       return OCPP16Constants.OCPP_RESPONSE_REJECTED;
     }
@@ -681,8 +692,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
     }
     if (
-      !Utils.isNullOrUndefined(commandPayload.connectorId) &&
-      Utils.isNotEmptyArray(
+      !isNullOrUndefined(commandPayload.connectorId) &&
+      isNotEmptyArray(
         chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles
       )
     ) {
@@ -694,10 +705,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       );
       return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED;
     }
-    if (Utils.isNullOrUndefined(commandPayload.connectorId)) {
+    if (isNullOrUndefined(commandPayload.connectorId)) {
       let clearedCP = false;
       const clearChargingProfiles = (connectorStatus: ConnectorStatus) => {
-        if (Utils.isNotEmptyArray(connectorStatus?.chargingProfiles)) {
+        if (isNotEmptyArray(connectorStatus?.chargingProfiles)) {
           connectorStatus?.chargingProfiles?.forEach(
             (chargingProfile: OCPP16ChargingProfile, index: number) => {
               let clearCurrentCP = false;
@@ -1062,7 +1073,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       return OCPP16Constants.OCPP_RESPONSE_EMPTY;
     }
     if (
-      !Utils.isNullOrUndefined(chargingStation.stationInfo.firmwareStatus) &&
+      !isNullOrUndefined(chargingStation.stationInfo.firmwareStatus) &&
       chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed
     ) {
       logger.warn(
@@ -1071,7 +1082,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       );
       return OCPP16Constants.OCPP_RESPONSE_EMPTY;
     }
-    const retrieveDate = Utils.convertToDate(commandPayload.retrieveDate);
+    const retrieveDate = convertToDate(commandPayload.retrieveDate);
     const now = Date.now();
     if (retrieveDate?.getTime() <= now) {
       this.runInAsyncScope(
@@ -1147,7 +1158,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
       OCPP16FirmwareStatus.DownloadFailed
     ) {
-      await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
+      await sleep(getRandomInteger(maxDelay, minDelay) * 1000);
       await chargingStation.ocppRequestService.requestHandler<
         OCPP16FirmwareStatusNotificationRequest,
         OCPP16FirmwareStatusNotificationResponse
@@ -1158,7 +1169,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         chargingStation.stationInfo?.firmwareUpgrade?.failureStatus;
       return;
     }
-    await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
+    await sleep(getRandomInteger(maxDelay, minDelay) * 1000);
     await chargingStation.ocppRequestService.requestHandler<
       OCPP16FirmwareStatusNotificationRequest,
       OCPP16FirmwareStatusNotificationResponse
@@ -1178,7 +1189,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
             waitTime / 1000
           } seconds before continuing firmware update simulation`
         );
-        await Utils.sleep(waitTime);
+        await sleep(waitTime);
         transactionsStarted = true;
         wasTransactionsStarted = true;
       } else {
@@ -1214,8 +1225,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         transactionsStarted = false;
       }
     } while (transactionsStarted);
-    !wasTransactionsStarted &&
-      (await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000));
+    !wasTransactionsStarted && (await sleep(getRandomInteger(maxDelay, minDelay) * 1000));
     if (
       ChargingStationUtils.checkChargingStation(chargingStation, chargingStation.logPrefix()) ===
       false
@@ -1233,7 +1243,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
       OCPP16FirmwareStatus.InstallationFailed
     ) {
-      await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
+      await sleep(getRandomInteger(maxDelay, minDelay) * 1000);
       await chargingStation.ocppRequestService.requestHandler<
         OCPP16FirmwareStatusNotificationRequest,
         OCPP16FirmwareStatusNotificationResponse
@@ -1245,7 +1255,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       return;
     }
     if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) {
-      await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000);
+      await sleep(getRandomInteger(maxDelay, minDelay) * 1000);
       await chargingStation.reset(OCPP16StopTransactionReason.REBOOT);
     }
   }
@@ -1279,9 +1289,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         ftpClient = new Client();
         const accessResponse = await ftpClient.access({
           host: uri.host,
-          ...(Utils.isNotEmptyString(uri.port) && { port: Utils.convertToInt(uri.port) }),
-          ...(Utils.isNotEmptyString(uri.username) && { user: uri.username }),
-          ...(Utils.isNotEmptyString(uri.password) && { password: uri.password }),
+          ...(isNotEmptyString(uri.port) && { port: convertToInt(uri.port) }),
+          ...(isNotEmptyString(uri.username) && { user: uri.username }),
+          ...(isNotEmptyString(uri.password) && { password: uri.password }),
         });
         let uploadResponse: FTPResponse;
         if (accessResponse.code === 220) {
@@ -1429,7 +1439,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
           return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
         case OCPP16MessageTrigger.StatusNotification:
           setTimeout(() => {
-            if (!Utils.isNullOrUndefined(commandPayload?.connectorId)) {
+            if (!isNullOrUndefined(commandPayload?.connectorId)) {
               chargingStation.ocppRequestService
                 .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
                   chargingStation,
index 7ff1fdb8d43b27da48147a789a1612c87644d8a4..fb5007247d51f464d6cdbbacc99a322a685ae0cc 100644 (file)
@@ -24,7 +24,7 @@ import {
   OCPPVersion,
   type RequestParams,
 } from '../../../types';
-import { Constants, Utils } from '../../../utils';
+import { Constants, generateUUID } from '../../../utils';
 import { OCPPRequestService } from '../OCPPRequestService';
 import type { OCPPResponseService } from '../OCPPResponseService';
 
@@ -137,7 +137,7 @@ export class OCPP16RequestService extends OCPPRequestService {
     if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) {
       return (await this.sendMessage(
         chargingStation,
-        Utils.generateUUID(),
+        generateUUID(),
         this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
         commandName,
         params
index 5d87f633e1f262004fb1232a157c5b5abd417976..fae1dd9c66e1555b6f5dfd33dd2bc8fc681a11e1 100644 (file)
@@ -50,7 +50,13 @@ import {
   type SetChargingProfileResponse,
   type UnlockConnectorResponse,
 } from '../../../types';
-import { Constants, Utils, buildUpdatedMessage, logger } from '../../../utils';
+import {
+  Constants,
+  buildUpdatedMessage,
+  convertToInt,
+  isNullOrUndefined,
+  logger,
+} from '../../../utils';
 import { OCPPResponseService } from '../OCPPResponseService';
 
 const moduleName = 'OCPP16ResponseService';
@@ -442,7 +448,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
         }
       }
     }
-    const authorizeConnectorIdDefined = !Utils.isNullOrUndefined(authorizeConnectorId);
+    const authorizeConnectorIdDefined = !isNullOrUndefined(authorizeConnectorId);
     if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) {
       authorizeConnectorIdDefined &&
         (chargingStation.getConnectorStatus(authorizeConnectorId).idTagAuthorized = true);
@@ -589,7 +595,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
           payload.transactionId
         }, converting to integer`
       );
-      payload.transactionId = Utils.convertToInt(payload.transactionId);
+      payload.transactionId = convertToInt(payload.transactionId);
     }
 
     if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
@@ -639,7 +645,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
       chargingStation.startMeterValues(
         transactionConnectorId,
         configuredMeterValueSampleInterval
-          ? Utils.convertToInt(configuredMeterValueSampleInterval.value) * 1000
+          ? convertToInt(configuredMeterValueSampleInterval.value) * 1000
           : Constants.DEFAULT_METER_VALUES_INTERVAL
       );
     } else {
@@ -678,7 +684,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
     const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
       requestPayload.transactionId
     );
-    if (Utils.isNullOrUndefined(transactionConnectorId)) {
+    if (isNullOrUndefined(transactionConnectorId)) {
       logger.error(
         `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${requestPayload.transactionId.toString()}`
       );
@@ -731,7 +737,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
       payload.idTagInfo?.status ?? 'undefined'
     }'`;
     if (
-      Utils.isNullOrUndefined(payload.idTagInfo) ||
+      isNullOrUndefined(payload.idTagInfo) ||
       payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED
     ) {
       logger.info(logMsg);
index 4ddeed559a0ce6bd37c4902ad7300202f773d8cb..aac11154a715305522355933900638dc5ad57afc 100644 (file)
@@ -29,7 +29,22 @@ import {
   type SampledValueTemplate,
   Voltage,
 } from '../../../types';
-import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../../../utils';
+import {
+  ACElectricUtils,
+  Constants,
+  DCElectricUtils,
+  convertToFloat,
+  convertToInt,
+  getRandomFloatFluctuatedRounded,
+  getRandomFloatRounded,
+  getRandomInteger,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isUndefined,
+  logger,
+  roundTo,
+} from '../../../utils';
 import { OCPPServiceUtils } from '../OCPPServiceUtils';
 
 export class OCPP16ServiceUtils extends OCPPServiceUtils {
@@ -71,18 +86,18 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       const socMaximumValue = 100;
       const socMinimumValue = socSampledValueTemplate.minimumValue ?? 0;
       const socSampledValueTemplateValue = socSampledValueTemplate.value
-        ? Utils.getRandomFloatFluctuatedRounded(
+        ? getRandomFloatFluctuatedRounded(
             parseInt(socSampledValueTemplate.value),
             socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
           )
-        : Utils.getRandomInteger(socMaximumValue, socMinimumValue);
+        : getRandomInteger(socMaximumValue, socMinimumValue);
       meterValue.sampledValue.push(
         OCPP16ServiceUtils.buildSampledValue(socSampledValueTemplate, socSampledValueTemplateValue)
       );
       const sampledValuesIndex = meterValue.sampledValue.length - 1;
       if (
-        Utils.convertToInt(meterValue.sampledValue[sampledValuesIndex].value) > socMaximumValue ||
-        Utils.convertToInt(meterValue.sampledValue[sampledValuesIndex].value) < socMinimumValue ||
+        convertToInt(meterValue.sampledValue[sampledValuesIndex].value) > socMaximumValue ||
+        convertToInt(meterValue.sampledValue[sampledValuesIndex].value) < socMinimumValue ||
         debug
       ) {
         logger.error(
@@ -109,7 +124,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         : chargingStation.getVoltageOut();
       const fluctuationPercent =
         voltageSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT;
-      const voltageMeasurandValue = Utils.getRandomFloatFluctuatedRounded(
+      const voltageMeasurandValue = getRandomFloatFluctuatedRounded(
         voltageSampledValueTemplateValue,
         fluctuationPercent
       );
@@ -143,7 +158,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           const fluctuationPhaseToNeutralPercent =
             voltagePhaseLineToNeutralSampledValueTemplate.fluctuationPercent ??
             Constants.DEFAULT_FLUCTUATION_PERCENT;
-          voltagePhaseLineToNeutralMeasurandValue = Utils.getRandomFloatFluctuatedRounded(
+          voltagePhaseLineToNeutralMeasurandValue = getRandomFloatFluctuatedRounded(
             voltagePhaseLineToNeutralSampledValueTemplateValue,
             fluctuationPhaseToNeutralPercent
           );
@@ -178,12 +193,12 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             const fluctuationPhaseLineToLinePercent =
               voltagePhaseLineToLineSampledValueTemplate.fluctuationPercent ??
               Constants.DEFAULT_FLUCTUATION_PERCENT;
-            voltagePhaseLineToLineMeasurandValue = Utils.getRandomFloatFluctuatedRounded(
+            voltagePhaseLineToLineMeasurandValue = getRandomFloatFluctuatedRounded(
               voltagePhaseLineToLineSampledValueTemplateValue,
               fluctuationPhaseLineToLinePercent
             );
           }
-          const defaultVoltagePhaseLineToLineMeasurandValue = Utils.getRandomFloatFluctuatedRounded(
+          const defaultVoltagePhaseLineToLineMeasurandValue = getRandomFloatFluctuatedRounded(
             Voltage.VOLTAGE_400,
             fluctuationPercent
           );
@@ -258,7 +273,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           if (chargingStation.getNumberOfPhases() === 3) {
             const defaultFluctuatedPowerPerPhase =
               powerSampledValueTemplate.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   powerSampledValueTemplate.value,
                   connectorMaximumPower / unitDivider,
@@ -269,7 +284,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase1FluctuatedValue =
               powerPerPhaseSampledValueTemplates?.L1?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   powerPerPhaseSampledValueTemplates.L1.value,
                   connectorMaximumPowerPerPhase / unitDivider,
@@ -280,7 +295,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase2FluctuatedValue =
               powerPerPhaseSampledValueTemplates?.L2?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   powerPerPhaseSampledValueTemplates.L2.value,
                   connectorMaximumPowerPerPhase / unitDivider,
@@ -291,7 +306,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase3FluctuatedValue =
               powerPerPhaseSampledValueTemplates?.L3?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   powerPerPhaseSampledValueTemplates.L3.value,
                   connectorMaximumPowerPerPhase / unitDivider,
@@ -303,27 +318,27 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             powerMeasurandValues.L1 =
               phase1FluctuatedValue ??
               defaultFluctuatedPowerPerPhase ??
-              Utils.getRandomFloatRounded(
+              getRandomFloatRounded(
                 connectorMaximumPowerPerPhase / unitDivider,
                 connectorMinimumPowerPerPhase / unitDivider
               );
             powerMeasurandValues.L2 =
               phase2FluctuatedValue ??
               defaultFluctuatedPowerPerPhase ??
-              Utils.getRandomFloatRounded(
+              getRandomFloatRounded(
                 connectorMaximumPowerPerPhase / unitDivider,
                 connectorMinimumPowerPerPhase / unitDivider
               );
             powerMeasurandValues.L3 =
               phase3FluctuatedValue ??
               defaultFluctuatedPowerPerPhase ??
-              Utils.getRandomFloatRounded(
+              getRandomFloatRounded(
                 connectorMaximumPowerPerPhase / unitDivider,
                 connectorMinimumPowerPerPhase / unitDivider
               );
           } else {
             powerMeasurandValues.L1 = powerSampledValueTemplate.value
-              ? Utils.getRandomFloatFluctuatedRounded(
+              ? getRandomFloatFluctuatedRounded(
                   OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                     powerSampledValueTemplate.value,
                     connectorMaximumPower / unitDivider,
@@ -332,21 +347,21 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                   powerSampledValueTemplate.fluctuationPercent ??
                     Constants.DEFAULT_FLUCTUATION_PERCENT
                 )
-              : Utils.getRandomFloatRounded(
+              : getRandomFloatRounded(
                   connectorMaximumPower / unitDivider,
                   connectorMinimumPower / unitDivider
                 );
             powerMeasurandValues.L2 = 0;
             powerMeasurandValues.L3 = 0;
           }
-          powerMeasurandValues.allPhases = Utils.roundTo(
+          powerMeasurandValues.allPhases = roundTo(
             powerMeasurandValues.L1 + powerMeasurandValues.L2 + powerMeasurandValues.L3,
             2
           );
           break;
         case CurrentType.DC:
           powerMeasurandValues.allPhases = powerSampledValueTemplate.value
-            ? Utils.getRandomFloatFluctuatedRounded(
+            ? getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   powerSampledValueTemplate.value,
                   connectorMaximumPower / unitDivider,
@@ -355,7 +370,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                 powerSampledValueTemplate.fluctuationPercent ??
                   Constants.DEFAULT_FLUCTUATION_PERCENT
               )
-            : Utils.getRandomFloatRounded(
+            : getRandomFloatRounded(
                 connectorMaximumPower / unitDivider,
                 connectorMinimumPower / unitDivider
               );
@@ -371,12 +386,12 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         )
       );
       const sampledValuesIndex = meterValue.sampledValue.length - 1;
-      const connectorMaximumPowerRounded = Utils.roundTo(connectorMaximumPower / unitDivider, 2);
-      const connectorMinimumPowerRounded = Utils.roundTo(connectorMinimumPower / unitDivider, 2);
+      const connectorMaximumPowerRounded = roundTo(connectorMaximumPower / unitDivider, 2);
+      const connectorMinimumPowerRounded = roundTo(connectorMinimumPower / unitDivider, 2);
       if (
-        Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
+        convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
           connectorMaximumPowerRounded ||
-        Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) <
+        convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) <
           connectorMinimumPowerRounded ||
         debug
       ) {
@@ -407,18 +422,18 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           )
         );
         const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
-        const connectorMaximumPowerPerPhaseRounded = Utils.roundTo(
+        const connectorMaximumPowerPerPhaseRounded = roundTo(
           connectorMaximumPowerPerPhase / unitDivider,
           2
         );
-        const connectorMinimumPowerPerPhaseRounded = Utils.roundTo(
+        const connectorMinimumPowerPerPhaseRounded = roundTo(
           connectorMinimumPowerPerPhase / unitDivider,
           2
         );
         if (
-          Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
+          convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
             connectorMaximumPowerPerPhaseRounded ||
-          Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) <
+          convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) <
             connectorMinimumPowerPerPhaseRounded ||
           debug
         ) {
@@ -495,7 +510,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           if (chargingStation.getNumberOfPhases() === 3) {
             const defaultFluctuatedAmperagePerPhase =
               currentSampledValueTemplate.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   currentSampledValueTemplate.value,
                   connectorMaximumAmperage,
@@ -506,7 +521,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase1FluctuatedValue =
               currentPerPhaseSampledValueTemplates?.L1?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   currentPerPhaseSampledValueTemplates.L1.value,
                   connectorMaximumAmperage,
@@ -517,7 +532,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase2FluctuatedValue =
               currentPerPhaseSampledValueTemplates?.L2?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   currentPerPhaseSampledValueTemplates.L2.value,
                   connectorMaximumAmperage,
@@ -528,7 +543,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               );
             const phase3FluctuatedValue =
               currentPerPhaseSampledValueTemplates?.L3?.value &&
-              Utils.getRandomFloatFluctuatedRounded(
+              getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   currentPerPhaseSampledValueTemplates.L3.value,
                   connectorMaximumAmperage,
@@ -540,18 +555,18 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             currentMeasurandValues.L1 =
               phase1FluctuatedValue ??
               defaultFluctuatedAmperagePerPhase ??
-              Utils.getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+              getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
             currentMeasurandValues.L2 =
               phase2FluctuatedValue ??
               defaultFluctuatedAmperagePerPhase ??
-              Utils.getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+              getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
             currentMeasurandValues.L3 =
               phase3FluctuatedValue ??
               defaultFluctuatedAmperagePerPhase ??
-              Utils.getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+              getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
           } else {
             currentMeasurandValues.L1 = currentSampledValueTemplate.value
-              ? Utils.getRandomFloatFluctuatedRounded(
+              ? getRandomFloatFluctuatedRounded(
                   OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                     currentSampledValueTemplate.value,
                     connectorMaximumAmperage,
@@ -560,11 +575,11 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                   currentSampledValueTemplate.fluctuationPercent ??
                     Constants.DEFAULT_FLUCTUATION_PERCENT
                 )
-              : Utils.getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+              : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
             currentMeasurandValues.L2 = 0;
             currentMeasurandValues.L3 = 0;
           }
-          currentMeasurandValues.allPhases = Utils.roundTo(
+          currentMeasurandValues.allPhases = roundTo(
             (currentMeasurandValues.L1 + currentMeasurandValues.L2 + currentMeasurandValues.L3) /
               chargingStation.getNumberOfPhases(),
             2
@@ -576,7 +591,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             chargingStation.getVoltageOut()
           );
           currentMeasurandValues.allPhases = currentSampledValueTemplate.value
-            ? Utils.getRandomFloatFluctuatedRounded(
+            ? getRandomFloatFluctuatedRounded(
                 OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
                   currentSampledValueTemplate.value,
                   connectorMaximumAmperage,
@@ -585,7 +600,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
                 currentSampledValueTemplate.fluctuationPercent ??
                   Constants.DEFAULT_FLUCTUATION_PERCENT
               )
-            : Utils.getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
+            : getRandomFloatRounded(connectorMaximumAmperage, connectorMinimumAmperage);
           break;
         default:
           logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
@@ -599,9 +614,9 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       );
       const sampledValuesIndex = meterValue.sampledValue.length - 1;
       if (
-        Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
+        convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) >
           connectorMaximumAmperage ||
-        Utils.convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) <
+        convertToFloat(meterValue.sampledValue[sampledValuesIndex].value) <
           connectorMinimumAmperage ||
         debug
       ) {
@@ -633,9 +648,9 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         );
         const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1;
         if (
-          Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
+          convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) >
             connectorMaximumAmperage ||
-          Utils.convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) <
+          convertToFloat(meterValue.sampledValue[sampledValuesPerPhaseIndex].value) <
             connectorMinimumAmperage ||
           debug
         ) {
@@ -668,13 +683,13 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         energySampledValueTemplate?.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1;
       const connectorMaximumAvailablePower =
         chargingStation.getConnectorMaximumAvailablePower(connectorId);
-      const connectorMaximumEnergyRounded = Utils.roundTo(
+      const connectorMaximumEnergyRounded = roundTo(
         (connectorMaximumAvailablePower * interval) / (3600 * 1000),
         2
       );
       const energyValueRounded = energySampledValueTemplate.value
         ? // Cumulate the fluctuated value around the static one
-          Utils.getRandomFloatFluctuatedRounded(
+          getRandomFloatFluctuatedRounded(
             OCPP16ServiceUtils.getLimitFromSampledValueTemplateCustomValue(
               energySampledValueTemplate.value,
               connectorMaximumEnergyRounded,
@@ -685,13 +700,13 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             ),
             energySampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
           )
-        : Utils.getRandomFloatRounded(connectorMaximumEnergyRounded);
+        : getRandomFloatRounded(connectorMaximumEnergyRounded);
       // Persist previous value on connector
       if (
         connector &&
-        Utils.isNullOrUndefined(connector.energyActiveImportRegisterValue) === false &&
+        isNullOrUndefined(connector.energyActiveImportRegisterValue) === false &&
         connector.energyActiveImportRegisterValue >= 0 &&
-        Utils.isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) === false &&
+        isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) === false &&
         connector.transactionEnergyActiveImportRegisterValue >= 0
       ) {
         connector.energyActiveImportRegisterValue += energyValueRounded;
@@ -703,7 +718,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       meterValue.sampledValue.push(
         OCPP16ServiceUtils.buildSampledValue(
           energySampledValueTemplate,
-          Utils.roundTo(
+          roundTo(
             chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) /
               unitDivider,
             2
@@ -718,7 +733,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
           }: connector id ${connectorId}, transaction id ${
             connector?.transactionId
-          }, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${Utils.roundTo(
+          }, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${roundTo(
             interval / (3600 * 1000),
             4
           )}h`
@@ -746,7 +761,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     meterValue.sampledValue.push(
       OCPP16ServiceUtils.buildSampledValue(
         sampledValueTemplate,
-        Utils.roundTo((meterStart ?? 0) / unitDivider, 4),
+        roundTo((meterStart ?? 0) / unitDivider, 4),
         MeterValueContext.TRANSACTION_BEGIN
       )
     );
@@ -771,7 +786,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     meterValue.sampledValue.push(
       OCPP16ServiceUtils.buildSampledValue(
         sampledValueTemplate,
-        Utils.roundTo((meterStop ?? 0) / unitDivider, 4),
+        roundTo((meterStop ?? 0) / unitDivider, 4),
         MeterValueContext.TRANSACTION_END
       )
     );
@@ -793,9 +808,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     connectorId: number,
     cp: OCPP16ChargingProfile
   ): void {
-    if (
-      Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)
-    ) {
+    if (isNullOrUndefined(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
       logger.error(
         `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
       );
@@ -810,7 +823,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
     }
     let cpReplaced = false;
-    if (Utils.isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
+    if (isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
       chargingStation
         .getConnectorStatus(connectorId)
         ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
@@ -876,16 +889,16 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       OCPP16ServiceUtils.getMeasurandDefaultLocation(sampledValueTemplate?.measurand ?? null);
     const sampledValuePhase = phase ?? sampledValueTemplate?.phase ?? null;
     return {
-      ...(!Utils.isNullOrUndefined(sampledValueTemplate.unit) && {
+      ...(!isNullOrUndefined(sampledValueTemplate.unit) && {
         unit: sampledValueTemplate.unit,
       }),
-      ...(!Utils.isNullOrUndefined(sampledValueContext) && { context: sampledValueContext }),
-      ...(!Utils.isNullOrUndefined(sampledValueTemplate.measurand) && {
+      ...(!isNullOrUndefined(sampledValueContext) && { context: sampledValueContext }),
+      ...(!isNullOrUndefined(sampledValueTemplate.measurand) && {
         measurand: sampledValueTemplate.measurand,
       }),
-      ...(!Utils.isNullOrUndefined(sampledValueLocation) && { location: sampledValueLocation }),
-      ...(!Utils.isNullOrUndefined(sampledValueValue) && { value: sampledValueValue.toString() }),
-      ...(!Utils.isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase }),
+      ...(!isNullOrUndefined(sampledValueLocation) && { location: sampledValueLocation }),
+      ...(!isNullOrUndefined(sampledValueValue) && { value: sampledValueValue.toString() }),
+      ...(!isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase }),
     };
   }
 
@@ -893,7 +906,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     chargingStation: ChargingStation,
     measurandType: OCPP16MeterValueMeasurand
   ): void {
-    if (Utils.isUndefined(chargingStation.powerDivider)) {
+    if (isUndefined(chargingStation.powerDivider)) {
       const errMsg = `MeterValues measurand ${
         measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
       }: powerDivider is undefined`;
@@ -943,7 +956,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     return (
       chargingStation.getLocalAuthListEnabled() === true &&
       chargingStation.hasIdTags() === true &&
-      Utils.isNotEmptyString(
+      isNotEmptyString(
         chargingStation.idTagsCache
           .getIdTags(ChargingStationUtils.getIdTagsFile(chargingStation.stationInfo))
           ?.find((tag) => tag === idTag)
index 6e857089d96a567c99e0599de561dd56eaccb990..15a3b5023facc5da4f0ddff007da470f1f1d5a18 100644 (file)
@@ -17,7 +17,7 @@ import {
   OCPPVersion,
   type RequestParams,
 } from '../../../types';
-import { Utils } from '../../../utils';
+import { generateUUID } from '../../../utils';
 import { OCPPRequestService } from '../OCPPRequestService';
 import type { OCPPResponseService } from '../OCPPResponseService';
 
@@ -74,7 +74,7 @@ export class OCPP20RequestService extends OCPPRequestService {
     if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName) === true) {
       return (await this.sendMessage(
         chargingStation,
-        Utils.generateUUID(),
+        generateUUID(),
         this.buildRequestPayload<RequestType>(chargingStation, commandName, commandParams),
         commandName,
         params
index a3b78ca63ec8e40d44a07c7a12f9689ed38eee63..443c6c802cb5e532f878262f7cf40357594343b2 100644 (file)
@@ -23,7 +23,13 @@ import {
   type ResponseCallback,
   type ResponseType,
 } from '../../types';
-import { Constants, Utils, handleSendMessageError, logger } from '../../utils';
+import {
+  Constants,
+  cloneObject,
+  handleSendMessageError,
+  logger,
+  promiseWithTimeout,
+} from '../../utils';
 
 const moduleName = 'OCPPRequestService';
 
@@ -201,7 +207,7 @@ export abstract class OCPPRequestService {
       return true;
     }
     const validate = this.ajv.compile(this.jsonSchemas.get(commandName as RequestCommand));
-    payload = Utils.cloneObject<T>(payload);
+    payload = cloneObject<T>(payload);
     OCPPServiceUtils.convertDateToISOString<T>(payload);
     if (validate(payload)) {
       return true;
@@ -242,7 +248,7 @@ export abstract class OCPPRequestService {
         commandName as IncomingRequestCommand
       )
     );
-    payload = Utils.cloneObject<T>(payload);
+    payload = cloneObject<T>(payload);
     OCPPServiceUtils.convertDateToISOString<T>(payload);
     if (validate(payload)) {
       return true;
@@ -284,7 +290,7 @@ export abstract class OCPPRequestService {
       // eslint-disable-next-line @typescript-eslint/no-this-alias
       const self = this;
       // Send a message through wsConnection
-      return Utils.promiseWithTimeout(
+      return promiseWithTimeout(
         new Promise((resolve, reject) => {
           /**
            * Function that will receive the request's response
index 7433f71d27c4278d39f77caa85315fb89b5daefb..8e2064905d7691525cd6b20fc885557b761b5cbb 100644 (file)
@@ -30,7 +30,13 @@ import {
   type StatusNotificationRequest,
   type StatusNotificationResponse,
 } from '../../types';
-import { Utils, handleFileException, logger } from '../../utils';
+import {
+  handleFileException,
+  isNotEmptyArray,
+  isNotEmptyString,
+  logPrefix,
+  logger,
+} from '../../utils';
 
 export class OCPPServiceUtils {
   protected constructor() {
@@ -314,7 +320,7 @@ export class OCPPServiceUtils {
       chargingStation.getConnectorStatus(connectorId)?.MeterValues;
     for (
       let index = 0;
-      Utils.isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length;
+      isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length;
       index++
     ) {
       if (
@@ -392,9 +398,9 @@ export class OCPPServiceUtils {
     methodName?: string
   ): string => {
     const logMsg =
-      Utils.isNotEmptyString(moduleName) && Utils.isNotEmptyString(methodName)
+      isNotEmptyString(moduleName) && isNotEmptyString(methodName)
         ? ` OCPP ${ocppVersion} | ${moduleName}.${methodName}:`
         : ` OCPP ${ocppVersion} |`;
-    return Utils.logPrefix(logMsg);
+    return logPrefix(logMsg);
   };
 }
index 159559df1f4cacb6eebaa1f67b8e6cca66ac030a..97eaa1193ca2e270535fd88f4977b3286b462876 100644 (file)
@@ -15,7 +15,14 @@ import {
   ResponseStatus,
   type UIServerConfiguration,
 } from '../../types';
-import { Constants, Utils, logger } from '../../utils';
+import {
+  Constants,
+  generateUUID,
+  isNotEmptyString,
+  isNullOrUndefined,
+  logPrefix,
+  logger,
+} from '../../utils';
 
 const moduleName = 'UIHttpServer';
 
@@ -69,10 +76,10 @@ export class UIHttpServer extends AbstractUIServer {
   public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
     const logMsgPrefix = prefixSuffix ? `UI HTTP Server ${prefixSuffix}` : 'UI HTTP Server';
     const logMsg =
-      Utils.isNotEmptyString(modName) && Utils.isNotEmptyString(methodName)
+      isNotEmptyString(modName) && isNotEmptyString(methodName)
         ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
         : ` ${logMsgPrefix} |`;
-    return Utils.logPrefix(logMsg);
+    return logPrefix(logMsg);
   };
 
   private requestListener(req: IncomingMessage, res: ServerResponse): void {
@@ -94,7 +101,7 @@ export class UIHttpServer extends AbstractUIServer {
       ProtocolVersion,
       ProcedureName
     ];
-    const uuid = Utils.generateUUID();
+    const uuid = generateUUID();
     this.responseHandlers.set(uuid, res);
     try {
       const fullProtocol = `${protocol}${version}`;
@@ -126,7 +133,7 @@ export class UIHttpServer extends AbstractUIServer {
                 )
               )
               .then((protocolResponse: ProtocolResponse) => {
-                if (!Utils.isNullOrUndefined(protocolResponse)) {
+                if (!isNullOrUndefined(protocolResponse)) {
                   this.sendResponse(protocolResponse);
                 }
               })
index 056d31fa8e0f0b37a9ec6101a0418b6d1c3d5fc4..cada139961dd0044686074eecbb158a0b6c16e7e 100644 (file)
@@ -1,7 +1,7 @@
 import type { IncomingMessage } from 'node:http';
 
 import { Protocol, ProtocolVersion } from '../../types';
-import { Utils, logger } from '../../utils';
+import { logPrefix, logger } from '../../utils';
 
 export class UIServerUtils {
   private constructor() {
@@ -24,7 +24,7 @@ export class UIServerUtils {
       }
     }
     logger.error(
-      `${Utils.logPrefix(
+      `${logPrefix(
         ' UI WebSocket Server |'
       )} Unsupported protocol: ${protocol} or protocol version: ${version}`
     );
index 09842bf67ffae1432537f26c69daba87a1864e99..2cd0267c18fb3cbb95b36abaaeede3a3f0cc5ef3 100644 (file)
@@ -12,7 +12,15 @@ import {
   type UIServerConfiguration,
   WebSocketCloseEventStatusCode,
 } from '../../types';
-import { Constants, Utils, logger } from '../../utils';
+import {
+  Constants,
+  getWebSocketCloseEventStatusString,
+  isNotEmptyString,
+  isNullOrUndefined,
+  logPrefix,
+  logger,
+  validateUUID,
+} from '../../utils';
 
 const moduleName = 'UIWebSocketServer';
 
@@ -53,7 +61,7 @@ export class UIWebSocketServer extends AbstractUIServer {
           .get(version)
           ?.requestHandler(request)
           .then((protocolResponse: ProtocolResponse) => {
-            if (!Utils.isNullOrUndefined(protocolResponse)) {
+            if (!isNullOrUndefined(protocolResponse)) {
               this.sendResponse(protocolResponse);
             }
           })
@@ -67,7 +75,7 @@ export class UIWebSocketServer extends AbstractUIServer {
           `${this.logPrefix(
             moduleName,
             'start.ws.onclose'
-          )} WebSocket closed: '${Utils.getWebSocketCloseEventStatusString(
+          )} WebSocket closed: '${getWebSocketCloseEventStatusString(
             code
           )}' - '${reason.toString()}'`
         );
@@ -152,10 +160,10 @@ export class UIWebSocketServer extends AbstractUIServer {
       ? `UI WebSocket Server ${prefixSuffix}`
       : 'UI WebSocket Server';
     const logMsg =
-      Utils.isNotEmptyString(modName) && Utils.isNotEmptyString(methodName)
+      isNotEmptyString(modName) && isNotEmptyString(methodName)
         ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
         : ` ${logMsgPrefix} |`;
-    return Utils.logPrefix(logMsg);
+    return logPrefix(logMsg);
   };
 
   private broadcastToClients(message: string): void {
@@ -195,7 +203,7 @@ export class UIWebSocketServer extends AbstractUIServer {
       return false;
     }
 
-    if (Utils.validateUUID(request[0]) === false) {
+    if (validateUUID(request[0]) === false) {
       logger.error(
         `${this.logPrefix(
           moduleName,
index 1ec6cf93b20e77363f08ecbb79cb9c10ed9cf656..bfe3751c4c20b73f1dd903b3c19458fca930f0ce 100644 (file)
@@ -11,7 +11,7 @@ import {
   type ResponsePayload,
   ResponseStatus,
 } from '../../../types';
-import { Utils, logger } from '../../../utils';
+import { isNotEmptyArray, isNullOrUndefined, logger } from '../../../utils';
 import { Bootstrap } from '../../Bootstrap';
 import { UIServiceWorkerBroadcastChannel } from '../../broadcast-channel/UIServiceWorkerBroadcastChannel';
 import type { AbstractUIServer } from '../AbstractUIServer';
@@ -100,7 +100,7 @@ export abstract class AbstractUIService {
         errorDetails: (error as OCPPError).details,
       };
     }
-    if (!Utils.isNullOrUndefined(responsePayload)) {
+    if (!isNullOrUndefined(responsePayload)) {
       return this.uiServer.buildProtocolResponse(messageId, responsePayload);
     }
   }
@@ -152,9 +152,9 @@ export abstract class AbstractUIService {
     procedureName: BroadcastChannelProcedureName,
     payload: BroadcastChannelRequestPayload
   ): void {
-    if (Utils.isNotEmptyArray(payload.hashIds)) {
+    if (isNotEmptyArray(payload.hashIds)) {
       payload.hashIds = payload.hashIds
-        .filter((hashId) => !Utils.isNullOrUndefined(hashId))
+        .filter((hashId) => !isNullOrUndefined(hashId))
         .map((hashId) => {
           if (this.uiServer.chargingStations.has(hashId) === true) {
             return hashId;
@@ -167,7 +167,7 @@ export abstract class AbstractUIService {
           );
         });
     }
-    const expectedNumberOfResponses = Utils.isNotEmptyArray(payload.hashIds)
+    const expectedNumberOfResponses = isNotEmptyArray(payload.hashIds)
       ? payload.hashIds.length
       : this.uiServer.chargingStations.size;
     this.uiServiceWorkerBroadcastChannel.sendRequest([uuid, procedureName, payload]);
index 80f53e54b80580c4ffa56b67c7b9a14b1b829b04..2733fd7430140a16a95166f1c40efae7287dcc97 100644 (file)
@@ -15,8 +15,11 @@ import {
   CircularArray,
   Configuration,
   Constants,
-  Utils,
+  JSONStringifyWithMapSupport,
   buildPerformanceStatisticsMessage,
+  formatDurationSeconds,
+  generateUUID,
+  logPrefix,
   logger,
   median,
   nthPercentile,
@@ -60,7 +63,7 @@ export class PerformanceStatistics {
   }
 
   public static beginMeasure(id: string): string {
-    const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${Utils.generateUUID()}`;
+    const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`;
     performance.mark(markId);
     return markId;
   }
@@ -160,7 +163,7 @@ export class PerformanceStatistics {
   private logStatistics(): void {
     logger.info(`${this.logPrefix()}`, {
       ...this.statistics,
-      statisticsData: Utils.JSONStringifyWithMapSupport(this.statistics.statisticsData),
+      statisticsData: JSONStringifyWithMapSupport(this.statistics.statisticsData),
     });
   }
 
@@ -173,13 +176,11 @@ export class PerformanceStatistics {
         this.logStatistics();
       }, logStatisticsInterval * 1000);
       logger.info(
-        `${this.logPrefix()} logged every ${Utils.formatDurationSeconds(logStatisticsInterval)}`
+        `${this.logPrefix()} logged every ${formatDurationSeconds(logStatisticsInterval)}`
       );
     } else if (this.displayInterval) {
       logger.info(
-        `${this.logPrefix()} already logged every ${Utils.formatDurationSeconds(
-          logStatisticsInterval
-        )}`
+        `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`
       );
     } else if (Configuration.getLog().enabled) {
       logger.info(
@@ -255,6 +256,6 @@ export class PerformanceStatistics {
   }
 
   private logPrefix = (): string => {
-    return Utils.logPrefix(` ${this.objName} | Performance statistics`);
+    return logPrefix(` ${this.objName} | Performance statistics`);
   };
 }
index e1a9a44ed796e66e5639c45660850cb7b54fdbf9..c4a9f7483e30060047607bdbad5a97e15fb7c91c 100644 (file)
@@ -6,7 +6,14 @@ import { dirname } from 'node:path';
 import { Storage } from './Storage';
 import { BaseError } from '../../exception';
 import { FileType, type Statistics } from '../../types';
-import { AsyncLock, AsyncLockType, Constants, Utils, handleFileException } from '../../utils';
+import {
+  AsyncLock,
+  AsyncLockType,
+  Constants,
+  JSONStringifyWithMapSupport,
+  handleFileException,
+  isNullOrUndefined,
+} from '../../utils';
 
 export class JsonFileStorage extends Storage {
   private fd: number | null = null;
@@ -25,11 +32,7 @@ export class JsonFileStorage extends Storage {
           ? (JSON.parse(fileData) as Statistics[])
           : [];
         performanceRecords.push(performanceStatistics);
-        writeFileSync(
-          this.dbName,
-          Utils.JSONStringifyWithMapSupport(performanceRecords, 2),
-          'utf8'
-        );
+        writeFileSync(this.dbName, JSONStringifyWithMapSupport(performanceRecords, 2), 'utf8');
       })
       .catch((error) => {
         handleFileException(
@@ -46,7 +49,7 @@ export class JsonFileStorage extends Storage {
 
   public open(): void {
     try {
-      if (Utils.isNullOrUndefined(this?.fd)) {
+      if (isNullOrUndefined(this?.fd)) {
         if (!existsSync(dirname(this.dbName))) {
           mkdirSync(dirname(this.dbName), { recursive: true });
         }
index 1360dabbad61aa2ec0feb3bde2fddfdd5d8b6d06..f0fda133d1862c703742e296e4b06e85876b2d81 100644 (file)
@@ -9,7 +9,7 @@ import {
   type Statistics,
   StorageType,
 } from '../../types';
-import { Utils, logger, setDefaultErrorParams } from '../../utils';
+import { isNullOrUndefined, logger, setDefaultErrorParams } from '../../utils';
 
 export abstract class Storage {
   protected readonly storageUri: URL;
@@ -29,7 +29,7 @@ export abstract class Storage {
   ): void {
     setDefaultErrorParams(params, { throwError: false, consoleOut: false });
     const inTableOrCollectionStr =
-      (!Utils.isNullOrUndefined(table) || !table) && ` in table or collection '${table}'`;
+      (!isNullOrUndefined(table) || !table) && ` in table or collection '${table}'`;
     logger.error(
       `${this.logPrefix} ${this.getDBNameFromStorageType(type)} error '${
         error.message
index e61730c75170c958dd0c9644a3a10eb8449099a2..d264afeca0d537f16cdea6cd112532f04b24f1d2 100644 (file)
@@ -1,4 +1,4 @@
-import { Utils } from './Utils';
+import { isNullOrUndefined } from './Utils';
 import type { ChargingStation } from '../charging-station';
 import type {
   ChargingStationAutomaticTransactionGeneratorConfiguration,
@@ -12,9 +12,7 @@ export const buildChargingStationAutomaticTransactionGeneratorConfiguration = (
 ): ChargingStationAutomaticTransactionGeneratorConfiguration => {
   return {
     automaticTransactionGenerator: chargingStation.getAutomaticTransactionGeneratorConfiguration(),
-    ...(!Utils.isNullOrUndefined(
-      chargingStation.automaticTransactionGenerator?.connectorsStatus
-    ) && {
+    ...(!isNullOrUndefined(chargingStation.automaticTransactionGenerator?.connectorsStatus) && {
       automaticTransactionGeneratorStatuses: [
         ...chargingStation.automaticTransactionGenerator.connectorsStatus.values(),
       ],
index e115aeb324a12b9709682f49855e3eacadb9856f..e5f8a7c03ca0d28e5c49bbb86165f3a9b3a86129 100644 (file)
@@ -7,7 +7,7 @@ import merge from 'just-merge';
 import { WorkerChoiceStrategies } from 'poolifier';
 
 import { Constants } from './Constants';
-import { Utils } from './Utils';
+import { hasOwnProp, isCFEnvironment, isNotEmptyString, isUndefined } from './Utils';
 import {
   ApplicationProtocol,
   type ConfigurationData,
@@ -42,7 +42,7 @@ export class Configuration {
   }
 
   public static getUIServer(): UIServerConfiguration {
-    if (Utils.hasOwnProp(Configuration.getConfig(), 'uiWebSocketServer')) {
+    if (hasOwnProp(Configuration.getConfig(), 'uiWebSocketServer')) {
       console.error(
         `${chalk.green(Configuration.logPrefix())} ${chalk.red(
           "Deprecated configuration section 'uiWebSocketServer' usage. Use 'uiServer' instead"
@@ -57,13 +57,13 @@ export class Configuration {
         port: Constants.DEFAULT_UI_SERVER_PORT,
       },
     };
-    if (Utils.hasOwnProp(Configuration.getConfig(), 'uiServer')) {
+    if (hasOwnProp(Configuration.getConfig(), 'uiServer')) {
       uiServerConfiguration = merge<UIServerConfiguration>(
         uiServerConfiguration,
         Configuration.getConfig()?.uiServer
       );
     }
-    if (Utils.isCFEnvironment() === true) {
+    if (isCFEnvironment() === true) {
       delete uiServerConfiguration.options?.host;
       uiServerConfiguration.options.port = parseInt(process.env.PORT);
     }
@@ -77,7 +77,7 @@ export class Configuration {
       type: StorageType.JSON_FILE,
       uri: this.getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
     };
-    if (Utils.hasOwnProp(Configuration.getConfig(), 'performanceStorage')) {
+    if (hasOwnProp(Configuration.getConfig(), 'performanceStorage')) {
       storageConfiguration = {
         ...storageConfiguration,
         ...Configuration.getConfig()?.performanceStorage,
@@ -109,7 +109,7 @@ export class Configuration {
       'Use it in charging station template instead'
     );
     // Read conf
-    if (Utils.hasOwnProp(Configuration.getConfig(), 'autoReconnectMaxRetries')) {
+    if (hasOwnProp(Configuration.getConfig(), 'autoReconnectMaxRetries')) {
       return Configuration.getConfig()?.autoReconnectMaxRetries;
     }
   }
@@ -120,13 +120,13 @@ export class Configuration {
       undefined,
       "Use 'stationTemplateUrls' instead"
     );
-    !Utils.isUndefined(Configuration.getConfig()['stationTemplateURLs']) &&
+    !isUndefined(Configuration.getConfig()['stationTemplateURLs']) &&
       (Configuration.getConfig().stationTemplateUrls = Configuration.getConfig()[
         'stationTemplateURLs'
       ] as StationTemplateUrl[]);
     Configuration.getConfig().stationTemplateUrls.forEach(
       (stationTemplateUrl: StationTemplateUrl) => {
-        if (!Utils.isUndefined(stationTemplateUrl['numberOfStation'])) {
+        if (!isUndefined(stationTemplateUrl['numberOfStation'])) {
           console.error(
             `${chalk.green(Configuration.logPrefix())} ${chalk.red(
               `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`
@@ -200,41 +200,41 @@ export class Configuration {
       rotate: true,
     };
     const deprecatedLogConfiguration: LogConfiguration = {
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logEnabled') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logEnabled') && {
         enabled: Configuration.getConfig()?.logEnabled,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logFile') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logFile') && {
         file: Configuration.getConfig()?.logFile,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logErrorFile') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logErrorFile') && {
         errorFile: Configuration.getConfig()?.logErrorFile,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logStatisticsInterval') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logStatisticsInterval') && {
         statisticsInterval: Configuration.getConfig()?.logStatisticsInterval,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logLevel') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logLevel') && {
         level: Configuration.getConfig()?.logLevel,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logConsole') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logConsole') && {
         console: Configuration.getConfig()?.logConsole,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logFormat') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logFormat') && {
         format: Configuration.getConfig()?.logFormat,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logRotate') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logRotate') && {
         rotate: Configuration.getConfig()?.logRotate,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logMaxFiles') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logMaxFiles') && {
         maxFiles: Configuration.getConfig()?.logMaxFiles,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'logMaxSize') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'logMaxSize') && {
         maxSize: Configuration.getConfig()?.logMaxSize,
       }),
     };
     const logConfiguration: LogConfiguration = {
       ...defaultLogConfiguration,
       ...deprecatedLogConfiguration,
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'log') && Configuration.getConfig()?.log),
+      ...(hasOwnProp(Configuration.getConfig(), 'log') && Configuration.getConfig()?.log),
     };
     return logConfiguration;
   }
@@ -295,25 +295,25 @@ export class Configuration {
       poolStrategy: WorkerChoiceStrategies.ROUND_ROBIN,
     };
     const deprecatedWorkerConfiguration: WorkerConfiguration = {
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'workerProcess') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'workerProcess') && {
         processType: Configuration.getConfig()?.workerProcess,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'workerStartDelay') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'workerStartDelay') && {
         startDelay: Configuration.getConfig()?.workerStartDelay,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'chargingStationsPerWorker') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'chargingStationsPerWorker') && {
         elementsPerWorker: Configuration.getConfig()?.chargingStationsPerWorker,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'elementStartDelay') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'elementStartDelay') && {
         elementStartDelay: Configuration.getConfig()?.elementStartDelay,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'workerPoolMinSize') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'workerPoolMinSize') && {
         poolMinSize: Configuration.getConfig()?.workerPoolMinSize,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'workerPoolMaxSize') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'workerPoolMaxSize') && {
         poolMaxSize: Configuration.getConfig()?.workerPoolMaxSize,
       }),
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'workerPoolStrategy') && {
+      ...(hasOwnProp(Configuration.getConfig(), 'workerPoolStrategy') && {
         poolStrategy:
           Configuration.getConfig()?.workerPoolStrategy ?? WorkerChoiceStrategies.ROUND_ROBIN,
       }),
@@ -321,8 +321,7 @@ export class Configuration {
     const workerConfiguration: WorkerConfiguration = {
       ...defaultWorkerConfiguration,
       ...deprecatedWorkerConfiguration,
-      ...(Utils.hasOwnProp(Configuration.getConfig(), 'worker') &&
-        Configuration.getConfig()?.worker),
+      ...(hasOwnProp(Configuration.getConfig(), 'worker') && Configuration.getConfig()?.worker),
     };
     return workerConfiguration;
   }
@@ -343,7 +342,7 @@ export class Configuration {
       undefined,
       "Use 'supervisionUrls' instead"
     );
-    !Utils.isUndefined(Configuration.getConfig()['supervisionURLs']) &&
+    !isUndefined(Configuration.getConfig()['supervisionURLs']) &&
       (Configuration.getConfig().supervisionUrls = Configuration.getConfig()['supervisionURLs'] as
         | string
         | string[]);
@@ -362,7 +361,7 @@ export class Configuration {
       undefined,
       "Use 'supervisionUrlDistribution' instead"
     );
-    return Utils.hasOwnProp(Configuration.getConfig(), 'supervisionUrlDistribution')
+    return hasOwnProp(Configuration.getConfig(), 'supervisionUrlDistribution')
       ? Configuration.getConfig()?.supervisionUrlDistribution
       : SupervisionUrlDistribution.ROUND_ROBIN;
   }
@@ -378,8 +377,8 @@ export class Configuration {
   ) {
     if (
       sectionName &&
-      !Utils.isUndefined(Configuration.getConfig()[sectionName]) &&
-      !Utils.isUndefined((Configuration.getConfig()[sectionName] as Record<string, unknown>)[key])
+      !isUndefined(Configuration.getConfig()[sectionName]) &&
+      !isUndefined((Configuration.getConfig()[sectionName] as Record<string, unknown>)[key])
     ) {
       console.error(
         `${chalk.green(Configuration.logPrefix())} ${chalk.red(
@@ -388,7 +387,7 @@ export class Configuration {
           }`
         )}`
       );
-    } else if (!Utils.isUndefined(Configuration.getConfig()[key])) {
+    } else if (!isUndefined(Configuration.getConfig()[key])) {
       console.error(
         `${chalk.green(Configuration.logPrefix())} ${chalk.red(
           `Deprecated configuration key '${key}' usage${
@@ -427,7 +426,7 @@ export class Configuration {
         if (filename?.trim().length > 0 && event === 'change') {
           // Nullify to force configuration file reading
           Configuration.configuration = null;
-          if (!Utils.isUndefined(Configuration.configurationChangeCallback)) {
+          if (!isUndefined(Configuration.configurationChangeCallback)) {
             Configuration.configurationChangeCallback().catch((error) => {
               throw typeof error === 'string' ? new Error(error) : error;
             });
@@ -450,7 +449,7 @@ export class Configuration {
     error: NodeJS.ErrnoException,
     logPrefix: string
   ): void {
-    const prefix = Utils.isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
+    const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
     let logMsg: string;
     switch (error.code) {
       case 'ENOENT':
index b4f52ba894a9e57891a04954bbe066b6b1d40ad8..0e3dbc50058c669c1c5a30a17c8ecbe14e9138c9 100644 (file)
@@ -1,7 +1,7 @@
 import chalk from 'chalk';
 
 import { logger } from './Logger';
-import { Utils } from './Utils';
+import { isNotEmptyString } from './Utils';
 import type { ChargingStation } from '../charging-station';
 import type {
   EmptyObject,
@@ -37,7 +37,7 @@ export const handleFileException = (
   params: HandleErrorParams<EmptyObject> = defaultErrorParams
 ): void => {
   setDefaultErrorParams(params);
-  const prefix = Utils.isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
+  const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
   let logMsg: string;
   switch (error.code) {
     case 'ENOENT':
index 5e40b72435bc461b5ca8a6494ee08541be830a56..d1d5d629ab575ba7f5b238896eba114624271275 100644 (file)
@@ -2,7 +2,7 @@ import { type FSWatcher, type WatchListener, readFileSync, watch } from 'node:fs
 
 import { handleFileException } from './ErrorUtils';
 import { logger } from './Logger';
-import { Utils } from './Utils';
+import { isNotEmptyString } from './Utils';
 import type { FileType, JsonType } from '../types';
 
 export const watchJsonFile = <T extends JsonType>(
@@ -11,7 +11,7 @@ export const watchJsonFile = <T extends JsonType>(
   logPrefix: string,
   refreshedVariable?: T,
   listener: WatchListener<string> = (event, filename) => {
-    if (Utils.isNotEmptyString(filename) && event === 'change') {
+    if (isNotEmptyString(filename) && event === 'change') {
       try {
         logger.debug(`${logPrefix} ${fileType} file ${file} have changed, reload`);
         refreshedVariable && (refreshedVariable = JSON.parse(readFileSync(file, 'utf8')) as T);
@@ -23,7 +23,7 @@ export const watchJsonFile = <T extends JsonType>(
     }
   }
 ): FSWatcher | undefined => {
-  if (Utils.isNotEmptyString(file)) {
+  if (isNotEmptyString(file)) {
     try {
       return watch(file, listener);
     } catch (error) {
index 92fe6909e3740aa932b133be1378de947347adff..3f94e63eb77f546cd33ad1be53771955092645b5 100644 (file)
@@ -4,7 +4,7 @@ import TransportType from 'winston/lib/winston/transports/index.js';
 import DailyRotateFile from 'winston-daily-rotate-file';
 
 import { Configuration } from './Configuration';
-import { Utils } from './Utils';
+import { insertAt } from './Utils';
 
 let transports: transport[];
 if (Configuration.getLog().rotate === true) {
@@ -12,7 +12,7 @@ if (Configuration.getLog().rotate === true) {
   const logMaxSize = Configuration.getLog().maxSize;
   transports = [
     new DailyRotateFile({
-      filename: Utils.insertAt(
+      filename: insertAt(
         Configuration.getLog().errorFile,
         '-%DATE%',
         Configuration.getLog().errorFile?.indexOf('.log')
@@ -22,7 +22,7 @@ if (Configuration.getLog().rotate === true) {
       ...(logMaxSize && { maxSize: logMaxSize }),
     }),
     new DailyRotateFile({
-      filename: Utils.insertAt(
+      filename: insertAt(
         Configuration.getLog().file,
         '-%DATE%',
         Configuration.getLog().file?.indexOf('.log')
index bb9a847091decf2ca488f83ad8c3d9d579d6e7fd..a2d906eb06c5e06af6b44ac9b8fb607b13a7b69c 100644 (file)
@@ -1,7 +1,7 @@
-import { Utils } from './Utils';
+import { isEmptyArray, isNullOrUndefined } from './Utils';
 
 export const median = (dataSet: number[]): number => {
-  if (Utils.isEmptyArray(dataSet)) {
+  if (isEmptyArray(dataSet)) {
     return 0;
   }
   if (Array.isArray(dataSet) === true && dataSet.length === 1) {
@@ -18,7 +18,7 @@ export const nthPercentile = (dataSet: number[], percentile: number): number =>
   if (percentile < 0 && percentile > 100) {
     throw new RangeError('Percentile is not between 0 and 100');
   }
-  if (Utils.isEmptyArray(dataSet)) {
+  if (isEmptyArray(dataSet)) {
     return 0;
   }
   const sortedDataSet = dataSet.slice().sort((a, b) => a - b);
@@ -30,7 +30,7 @@ export const nthPercentile = (dataSet: number[], percentile: number): number =>
   }
   const percentileIndexBase = (percentile / 100) * (sortedDataSet.length - 1);
   const percentileIndexInteger = Math.floor(percentileIndexBase);
-  if (!Utils.isNullOrUndefined(sortedDataSet[percentileIndexInteger + 1])) {
+  if (!isNullOrUndefined(sortedDataSet[percentileIndexInteger + 1])) {
     return (
       sortedDataSet[percentileIndexInteger] +
       (percentileIndexBase - percentileIndexInteger) *
index 7b0c9239e0a68ecb05e33fdbe1948b884d68fdaa..f15224a855b7e08e53e75e4221bb1009a80f19cd 100644 (file)
@@ -6,342 +6,328 @@ import clone from 'just-clone';
 import { Constants } from './Constants';
 import { WebSocketCloseEventStatusString } from '../types';
 
-export class Utils {
-  private constructor() {
-    // This is intentional
-  }
+export const logPrefix = (prefixString = ''): string => {
+  return `${new Date().toLocaleString()}${prefixString}`;
+};
 
-  public static logPrefix = (prefixString = ''): string => {
-    return `${new Date().toLocaleString()}${prefixString}`;
-  };
+export const generateUUID = (): string => {
+  return randomUUID();
+};
 
-  public static generateUUID(): string {
-    return randomUUID();
-  }
+export const validateUUID = (uuid: string): boolean => {
+  return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(
+    uuid
+  );
+};
 
-  public static validateUUID(uuid: string): boolean {
-    return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(
-      uuid
-    );
-  }
+export const sleep = async (milliSeconds: number): Promise<NodeJS.Timeout> => {
+  return new Promise((resolve) => setTimeout(resolve as () => void, milliSeconds));
+};
 
-  public static async sleep(milliSeconds: number): Promise<NodeJS.Timeout> {
-    return new Promise((resolve) => setTimeout(resolve as () => void, milliSeconds));
-  }
+export const formatDurationMilliSeconds = (duration: number): string => {
+  duration = convertToInt(duration);
+  const hours = Math.floor(duration / (3600 * 1000));
+  const minutes = Math.floor((duration / 1000 - hours * 3600) / 60);
+  const seconds = duration / 1000 - hours * 3600 - minutes * 60;
+  let hoursStr = hours.toString();
+  let minutesStr = minutes.toString();
+  let secondsStr = seconds.toString();
 
-  public static formatDurationMilliSeconds(duration: number): string {
-    duration = Utils.convertToInt(duration);
-    const hours = Math.floor(duration / (3600 * 1000));
-    const minutes = Math.floor((duration / 1000 - hours * 3600) / 60);
-    const seconds = duration / 1000 - hours * 3600 - minutes * 60;
-    let hoursStr = hours.toString();
-    let minutesStr = minutes.toString();
-    let secondsStr = seconds.toString();
-
-    if (hours < 10) {
-      hoursStr = `0${hours.toString()}`;
-    }
-    if (minutes < 10) {
-      minutesStr = `0${minutes.toString()}`;
-    }
-    if (seconds < 10) {
-      secondsStr = `0${seconds.toString()}`;
-    }
-    return `${hoursStr}:${minutesStr}:${secondsStr.substring(0, 6)}`;
+  if (hours < 10) {
+    hoursStr = `0${hours.toString()}`;
   }
-
-  public static formatDurationSeconds(duration: number): string {
-    return Utils.formatDurationMilliSeconds(duration * 1000);
+  if (minutes < 10) {
+    minutesStr = `0${minutes.toString()}`;
   }
-
-  public static convertToDate(
-    value: Date | string | number | null | undefined
-  ): Date | null | undefined {
-    if (Utils.isNullOrUndefined(value)) {
-      return value as null | undefined;
-    }
-    if (value instanceof Date) {
-      return value;
-    }
-    if (Utils.isString(value) || typeof value === 'number') {
-      return new Date(value);
-    }
-    return null;
+  if (seconds < 10) {
+    secondsStr = `0${seconds.toString()}`;
   }
+  return `${hoursStr}:${minutesStr}:${secondsStr.substring(0, 6)}`;
+};
 
-  public static convertToInt(value: unknown): number {
-    if (!value) {
-      return 0;
-    }
-    let changedValue: number = value as number;
-    if (Number.isSafeInteger(value)) {
-      return value as number;
-    }
-    if (typeof value === 'number') {
-      return Math.trunc(value);
-    }
-    if (Utils.isString(value)) {
-      changedValue = parseInt(value as string);
-    }
-    if (isNaN(changedValue)) {
-      throw new Error(`Cannot convert to integer: ${value.toString()}`);
-    }
-    return changedValue;
-  }
+export const formatDurationSeconds = (duration: number): string => {
+  return formatDurationMilliSeconds(duration * 1000);
+};
 
-  public static convertToFloat(value: unknown): number {
-    if (!value) {
-      return 0;
-    }
-    let changedValue: number = value as number;
-    if (Utils.isString(value)) {
-      changedValue = parseFloat(value as string);
-    }
-    if (isNaN(changedValue)) {
-      throw new Error(`Cannot convert to float: ${value.toString()}`);
-    }
-    return changedValue;
+export const convertToDate = (
+  value: Date | string | number | null | undefined
+): Date | null | undefined => {
+  if (isNullOrUndefined(value)) {
+    return value as null | undefined;
   }
-
-  public static convertToBoolean(value: unknown): boolean {
-    let result = false;
-    if (value) {
-      // Check the type
-      if (typeof value === 'boolean') {
-        return value;
-      } else if (
-        Utils.isString(value) &&
-        ((value as string).toLowerCase() === 'true' || value === '1')
-      ) {
-        result = true;
-      } else if (typeof value === 'number' && value === 1) {
-        result = true;
-      }
-    }
-    return result;
+  if (value instanceof Date) {
+    return value;
   }
-
-  public static getRandomFloat(max = Number.MAX_VALUE, min = 0): number {
-    if (max < min) {
-      throw new RangeError('Invalid interval');
-    }
-    if (max - min === Infinity) {
-      throw new RangeError('Invalid interval');
-    }
-    return (randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min;
+  if (isString(value) || typeof value === 'number') {
+    return new Date(value);
   }
+  return null;
+};
 
-  public static getRandomInteger(max = Constants.MAX_RANDOM_INTEGER, min = 0): number {
-    max = Math.floor(max);
-    if (!Utils.isNullOrUndefined(min) && min !== 0) {
-      min = Math.ceil(min);
-      return Math.floor(randomInt(min, max + 1));
-    }
-    return Math.floor(randomInt(max + 1));
+export const convertToInt = (value: unknown): number => {
+  if (!value) {
+    return 0;
   }
-
-  /**
-   * Rounds the given number to the given scale.
-   * The rounding is done using the "round half away from zero" method.
-   *
-   * @param numberValue - The number to round.
-   * @param scale - The scale to round to.
-   * @returns The rounded number.
-   */
-  public static roundTo(numberValue: number, scale: number): number {
-    const roundPower = Math.pow(10, scale);
-    return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower;
+  let changedValue: number = value as number;
+  if (Number.isSafeInteger(value)) {
+    return value as number;
   }
-
-  public static getRandomFloatRounded(max = Number.MAX_VALUE, min = 0, scale = 2): number {
-    if (min) {
-      return Utils.roundTo(Utils.getRandomFloat(max, min), scale);
-    }
-    return Utils.roundTo(Utils.getRandomFloat(max), scale);
+  if (typeof value === 'number') {
+    return Math.trunc(value);
   }
-
-  public static getRandomFloatFluctuatedRounded(
-    staticValue: number,
-    fluctuationPercent: number,
-    scale = 2
-  ): number {
-    if (fluctuationPercent < 0 || fluctuationPercent > 100) {
-      throw new RangeError(
-        `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent}`
-      );
-    }
-    if (fluctuationPercent === 0) {
-      return Utils.roundTo(staticValue, scale);
-    }
-    const fluctuationRatio = fluctuationPercent / 100;
-    return Utils.getRandomFloatRounded(
-      staticValue * (1 + fluctuationRatio),
-      staticValue * (1 - fluctuationRatio),
-      scale
-    );
+  if (isString(value)) {
+    changedValue = parseInt(value as string);
   }
-
-  public static isObject(item: unknown): boolean {
-    return (
-      Utils.isNullOrUndefined(item) === false &&
-      typeof item === 'object' &&
-      Array.isArray(item) === false
-    );
-  }
-
-  public static cloneObject<T extends object>(object: T): T {
-    return clone<T>(object);
-  }
-
-  public static hasOwnProp(object: unknown, property: PropertyKey): boolean {
-    return Utils.isObject(object) && Object.hasOwn(object as object, property);
+  if (isNaN(changedValue)) {
+    throw new Error(`Cannot convert to integer: ${value.toString()}`);
   }
+  return changedValue;
+};
 
-  public static isCFEnvironment(): boolean {
-    return !Utils.isNullOrUndefined(process.env.VCAP_APPLICATION);
+export const convertToFloat = (value: unknown): number => {
+  if (!value) {
+    return 0;
   }
-
-  public static isIterable<T>(obj: T): boolean {
-    return !Utils.isNullOrUndefined(obj) ? typeof obj[Symbol.iterator] === 'function' : false;
-  }
-
-  public static isString(value: unknown): boolean {
-    return typeof value === 'string';
+  let changedValue: number = value as number;
+  if (isString(value)) {
+    changedValue = parseFloat(value as string);
   }
-
-  public static isEmptyString(value: unknown): boolean {
-    return (
-      Utils.isNullOrUndefined(value) ||
-      (Utils.isString(value) && (value as string).trim().length === 0)
-    );
+  if (isNaN(changedValue)) {
+    throw new Error(`Cannot convert to float: ${value.toString()}`);
   }
+  return changedValue;
+};
 
-  public static isNotEmptyString(value: unknown): boolean {
-    return Utils.isString(value) && (value as string).trim().length > 0;
-  }
-
-  public static isUndefined(value: unknown): boolean {
-    return value === undefined;
-  }
-
-  public static isNullOrUndefined(value: unknown): boolean {
-    // eslint-disable-next-line eqeqeq, no-eq-null
-    return value == null;
-  }
-
-  public static isEmptyArray(object: unknown): boolean {
-    return Array.isArray(object) && object.length === 0;
-  }
-
-  public static isNotEmptyArray(object: unknown): boolean {
-    return Array.isArray(object) && object.length > 0;
-  }
-
-  public static isEmptyObject(obj: object): boolean {
-    if (obj?.constructor !== Object) {
-      return false;
-    }
-    // Iterates over the keys of an object, if
-    // any exist, return false.
-    for (const _ in obj) {
-      return false;
-    }
-    return true;
-  }
-
-  public static insertAt = (str: string, subStr: string, pos: number): string =>
-    `${str.slice(0, pos)}${subStr}${str.slice(pos)}`;
-
-  /**
-   * Computes the retry delay in milliseconds using an exponential backoff algorithm.
-   *
-   * @param retryNumber - the number of retries that have already been attempted
-   * @returns delay in milliseconds
-   */
-  public static exponentialDelay(retryNumber = 0, maxDelayRatio = 0.2): number {
-    const delay = Math.pow(2, retryNumber) * 100;
-    const randomSum = delay * maxDelayRatio * Utils.secureRandom(); // 0-20% of the delay
-    return delay + randomSum;
-  }
-
-  public static isPromisePending(promise: Promise<unknown>): boolean {
-    return inspect(promise).includes('pending');
-  }
-
-  public static async promiseWithTimeout<T>(
-    promise: Promise<T>,
-    timeoutMs: number,
-    timeoutError: Error,
-    timeoutCallback: () => void = () => {
-      /* This is intentional */
+export const convertToBoolean = (value: unknown): boolean => {
+  let result = false;
+  if (value) {
+    // Check the type
+    if (typeof value === 'boolean') {
+      return value;
+    } else if (isString(value) && ((value as string).toLowerCase() === 'true' || value === '1')) {
+      result = true;
+    } else if (typeof value === 'number' && value === 1) {
+      result = true;
     }
-  ): Promise<T> {
-    // Create a timeout promise that rejects in timeout milliseconds
-    const timeoutPromise = new Promise<never>((_, reject) => {
-      setTimeout(() => {
-        if (Utils.isPromisePending(promise)) {
-          timeoutCallback();
-          // FIXME: The original promise shall be canceled
-        }
-        reject(timeoutError);
-      }, timeoutMs);
-    });
-
-    // Returns a race between timeout promise and the passed promise
-    return Promise.race<T>([promise, timeoutPromise]);
-  }
-
-  /**
-   * Generates a cryptographically secure random number in the [0,1[ range
-   *
-   * @returns
-   */
-  public static secureRandom(): number {
-    return randomBytes(4).readUInt32LE() / 0x100000000;
   }
-
-  public static JSONStringifyWithMapSupport(
-    obj: Record<string, unknown> | Record<string, unknown>[] | Map<unknown, unknown>,
-    space?: number
-  ): string {
-    return JSON.stringify(
-      obj,
-      (key, value: Record<string, unknown>) => {
-        if (value instanceof Map) {
-          return {
-            dataType: 'Map',
-            value: [...value],
-          };
-        }
-        return value;
-      },
-      space
+  return result;
+};
+
+export const getRandomFloat = (max = Number.MAX_VALUE, min = 0): number => {
+  if (max < min) {
+    throw new RangeError('Invalid interval');
+  }
+  if (max - min === Infinity) {
+    throw new RangeError('Invalid interval');
+  }
+  return (randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min;
+};
+
+export const getRandomInteger = (max = Constants.MAX_RANDOM_INTEGER, min = 0): number => {
+  max = Math.floor(max);
+  if (!isNullOrUndefined(min) && min !== 0) {
+    min = Math.ceil(min);
+    return Math.floor(randomInt(min, max + 1));
+  }
+  return Math.floor(randomInt(max + 1));
+};
+
+/**
+ * Rounds the given number to the given scale.
+ * The rounding is done using the "round half away from zero" method.
+ *
+ * @param numberValue - The number to round.
+ * @param scale - The scale to round to.
+ * @returns The rounded number.
+ */
+export const roundTo = (numberValue: number, scale: number): number => {
+  const roundPower = Math.pow(10, scale);
+  return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower;
+};
+
+export const getRandomFloatRounded = (max = Number.MAX_VALUE, min = 0, scale = 2): number => {
+  if (min) {
+    return roundTo(getRandomFloat(max, min), scale);
+  }
+  return roundTo(getRandomFloat(max), scale);
+};
+
+export const getRandomFloatFluctuatedRounded = (
+  staticValue: number,
+  fluctuationPercent: number,
+  scale = 2
+): number => {
+  if (fluctuationPercent < 0 || fluctuationPercent > 100) {
+    throw new RangeError(
+      `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent}`
     );
   }
-
-  /**
-   * Converts websocket error code to human readable string message
-   *
-   * @param code - websocket error code
-   * @returns human readable string message
-   */
-  public static getWebSocketCloseEventStatusString(code: number): string {
-    if (code >= 0 && code <= 999) {
-      return '(Unused)';
-    } else if (code >= 1016) {
-      if (code <= 1999) {
-        return '(For WebSocket standard)';
-      } else if (code <= 2999) {
-        return '(For WebSocket extensions)';
-      } else if (code <= 3999) {
-        return '(For libraries and frameworks)';
-      } else if (code <= 4999) {
-        return '(For applications)';
+  if (fluctuationPercent === 0) {
+    return roundTo(staticValue, scale);
+  }
+  const fluctuationRatio = fluctuationPercent / 100;
+  return getRandomFloatRounded(
+    staticValue * (1 + fluctuationRatio),
+    staticValue * (1 - fluctuationRatio),
+    scale
+  );
+};
+
+export const isObject = (item: unknown): boolean => {
+  return (
+    isNullOrUndefined(item) === false && typeof item === 'object' && Array.isArray(item) === false
+  );
+};
+
+export const cloneObject = <T extends object>(object: T): T => {
+  return clone<T>(object);
+};
+
+export const hasOwnProp = (object: unknown, property: PropertyKey): boolean => {
+  return isObject(object) && Object.hasOwn(object as object, property);
+};
+
+export const isCFEnvironment = (): boolean => {
+  return !isNullOrUndefined(process.env.VCAP_APPLICATION);
+};
+
+export const isIterable = <T>(obj: T): boolean => {
+  return !isNullOrUndefined(obj) ? typeof obj[Symbol.iterator] === 'function' : false;
+};
+
+const isString = (value: unknown): boolean => {
+  return typeof value === 'string';
+};
+
+export const isEmptyString = (value: unknown): boolean => {
+  return isNullOrUndefined(value) || (isString(value) && (value as string).trim().length === 0);
+};
+
+export const isNotEmptyString = (value: unknown): boolean => {
+  return isString(value) && (value as string).trim().length > 0;
+};
+
+export const isUndefined = (value: unknown): boolean => {
+  return value === undefined;
+};
+
+export const isNullOrUndefined = (value: unknown): boolean => {
+  // eslint-disable-next-line eqeqeq, no-eq-null
+  return value == null;
+};
+
+export const isEmptyArray = (object: unknown): boolean => {
+  return Array.isArray(object) && object.length === 0;
+};
+
+export const isNotEmptyArray = (object: unknown): boolean => {
+  return Array.isArray(object) && object.length > 0;
+};
+
+export const isEmptyObject = (obj: object): boolean => {
+  if (obj?.constructor !== Object) {
+    return false;
+  }
+  // Iterates over the keys of an object, if
+  // any exist, return false.
+  for (const _ in obj) {
+    return false;
+  }
+  return true;
+};
+
+export const insertAt = (str: string, subStr: string, pos: number): string =>
+  `${str.slice(0, pos)}${subStr}${str.slice(pos)}`;
+
+/**
+ * Computes the retry delay in milliseconds using an exponential backoff algorithm.
+ *
+ * @param retryNumber - the number of retries that have already been attempted
+ * @returns delay in milliseconds
+ */
+export const exponentialDelay = (retryNumber = 0, maxDelayRatio = 0.2): number => {
+  const delay = Math.pow(2, retryNumber) * 100;
+  const randomSum = delay * maxDelayRatio * secureRandom(); // 0-20% of the delay
+  return delay + randomSum;
+};
+
+const isPromisePending = (promise: Promise<unknown>): boolean => {
+  return inspect(promise).includes('pending');
+};
+
+export const promiseWithTimeout = async <T>(
+  promise: Promise<T>,
+  timeoutMs: number,
+  timeoutError: Error,
+  timeoutCallback: () => void = () => {
+    /* This is intentional */
+  }
+): Promise<T> => {
+  // Create a timeout promise that rejects in timeout milliseconds
+  const timeoutPromise = new Promise<never>((_, reject) => {
+    setTimeout(() => {
+      if (isPromisePending(promise)) {
+        timeoutCallback();
+        // FIXME: The original promise shall be canceled
       }
+      reject(timeoutError);
+    }, timeoutMs);
+  });
+
+  // Returns a race between timeout promise and the passed promise
+  return Promise.race<T>([promise, timeoutPromise]);
+};
+
+/**
+ * Generates a cryptographically secure random number in the [0,1[ range
+ *
+ * @returns
+ */
+export const secureRandom = (): number => {
+  return randomBytes(4).readUInt32LE() / 0x100000000;
+};
+
+export const JSONStringifyWithMapSupport = (
+  obj: Record<string, unknown> | Record<string, unknown>[] | Map<unknown, unknown>,
+  space?: number
+): string => {
+  return JSON.stringify(
+    obj,
+    (key, value: Record<string, unknown>) => {
+      if (value instanceof Map) {
+        return {
+          dataType: 'Map',
+          value: [...value],
+        };
+      }
+      return value;
+    },
+    space
+  );
+};
+
+/**
+ * Converts websocket error code to human readable string message
+ *
+ * @param code - websocket error code
+ * @returns human readable string message
+ */
+export const getWebSocketCloseEventStatusString = (code: number): string => {
+  if (code >= 0 && code <= 999) {
+    return '(Unused)';
+  } else if (code >= 1016) {
+    if (code <= 1999) {
+      return '(For WebSocket standard)';
+    } else if (code <= 2999) {
+      return '(For WebSocket extensions)';
+    } else if (code <= 3999) {
+      return '(For libraries and frameworks)';
+    } else if (code <= 4999) {
+      return '(For applications)';
     }
-    if (!Utils.isUndefined(WebSocketCloseEventStatusString[code])) {
-      return WebSocketCloseEventStatusString[code] as string;
-    }
-    return '(Unknown)';
   }
-}
+  if (!isUndefined(WebSocketCloseEventStatusString[code])) {
+    return WebSocketCloseEventStatusString[code] as string;
+  }
+  return '(Unknown)';
+};
index b2374d7361e6ee0c0d3d4f0a74edeb8259eea1e9..93eae31e58dea8f77ea542e2ce12fb1f0d81bb38 100644 (file)
@@ -23,6 +23,34 @@ export {
   buildStartedMessage,
   buildStoppedMessage,
 } from './MessageChannelUtils';
-export { Utils } from './Utils';
+export {
+  JSONStringifyWithMapSupport,
+  cloneObject,
+  convertToBoolean,
+  convertToDate,
+  convertToFloat,
+  convertToInt,
+  exponentialDelay,
+  formatDurationMilliSeconds,
+  formatDurationSeconds,
+  generateUUID,
+  getRandomFloatFluctuatedRounded,
+  getRandomFloatRounded,
+  getRandomInteger,
+  getWebSocketCloseEventStatusString,
+  isEmptyArray,
+  isEmptyObject,
+  isEmptyString,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isUndefined,
+  logPrefix,
+  promiseWithTimeout,
+  roundTo,
+  secureRandom,
+  sleep,
+  validateUUID,
+} from './Utils';
 export { median, nthPercentile, stdDeviation } from './StatisticUtils';
 export { logger } from './Logger';
index 60d2e2aeee57278873765a47894beff72ed9ce9f..892f25a56462aea681eeda17aa737cf1150494c0 100644 (file)
 import { expect } from 'expect';
 
 import { Constants } from '../../src/utils/Constants';
-import { Utils } from '../../src/utils/Utils';
+import {
+  cloneObject,
+  convertToBoolean,
+  convertToDate,
+  convertToFloat,
+  convertToInt,
+  generateUUID,
+  getRandomFloat,
+  getRandomInteger,
+  hasOwnProp,
+  isEmptyArray,
+  isEmptyObject,
+  isEmptyString,
+  isIterable,
+  isNotEmptyArray,
+  isNotEmptyString,
+  isNullOrUndefined,
+  isObject,
+  isUndefined,
+  roundTo,
+  secureRandom,
+  sleep,
+  validateUUID,
+} from '../../src/utils/Utils';
 
 describe('Utils test suite', () => {
   it('Verify generateUUID()/validateUUID()', () => {
-    const uuid = Utils.generateUUID();
+    const uuid = generateUUID();
     expect(uuid).toBeDefined();
     expect(uuid.length).toEqual(36);
-    expect(Utils.validateUUID(uuid)).toBe(true);
-    expect(Utils.validateUUID('abcdef00-0000-4000-0000-000000000000')).toBe(true);
-    expect(Utils.validateUUID('')).toBe(false);
+    expect(validateUUID(uuid)).toBe(true);
+    expect(validateUUID('abcdef00-0000-4000-0000-000000000000')).toBe(true);
+    expect(validateUUID('')).toBe(false);
     // Shall invalidate Nil UUID
-    expect(Utils.validateUUID('00000000-0000-0000-0000-000000000000')).toBe(false);
-    expect(Utils.validateUUID('987FBC9-4BED-3078-CF07A-9141BA07C9F3')).toBe(false);
+    expect(validateUUID('00000000-0000-0000-0000-000000000000')).toBe(false);
+    expect(validateUUID('987FBC9-4BED-3078-CF07A-9141BA07C9F3')).toBe(false);
   });
 
   it('Verify sleep()', async () => {
     const start = performance.now();
-    await Utils.sleep(1000);
+    await sleep(1000);
     const end = performance.now();
     expect(end - start).toBeGreaterThanOrEqual(1000);
   });
 
   it('Verify convertToDate()', () => {
-    expect(Utils.convertToDate(undefined)).toBe(undefined);
-    expect(Utils.convertToDate(null)).toBe(null);
-    const invalidDate = Utils.convertToDate('');
+    expect(convertToDate(undefined)).toBe(undefined);
+    expect(convertToDate(null)).toBe(null);
+    const invalidDate = convertToDate('');
     expect(invalidDate instanceof Date && !isNaN(invalidDate.getTime())).toBe(false);
-    expect(Utils.convertToDate(0)).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'));
+    expect(convertToDate(0)).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'));
     const dateStr = '2020-01-01T00:00:00.000Z';
-    let date = Utils.convertToDate(dateStr);
+    let date = convertToDate(dateStr);
     expect(date).toBeInstanceOf(Date);
     expect(date).toStrictEqual(new Date(dateStr));
-    date = Utils.convertToDate(new Date(dateStr));
+    date = convertToDate(new Date(dateStr));
     expect(date).toBeInstanceOf(Date);
     expect(date).toStrictEqual(new Date(dateStr));
   });
 
   it('Verify convertToInt()', () => {
-    expect(Utils.convertToInt(undefined)).toBe(0);
-    expect(Utils.convertToInt(null)).toBe(0);
-    expect(Utils.convertToInt(0)).toBe(0);
-    const randomInteger = Utils.getRandomInteger();
-    expect(Utils.convertToInt(randomInteger)).toEqual(randomInteger);
-    expect(Utils.convertToInt('-1')).toBe(-1);
-    expect(Utils.convertToInt('1')).toBe(1);
-    expect(Utils.convertToInt('1.1')).toBe(1);
-    expect(Utils.convertToInt('1.9')).toBe(1);
-    expect(Utils.convertToInt('1.999')).toBe(1);
-    expect(Utils.convertToInt(-1)).toBe(-1);
-    expect(Utils.convertToInt(1)).toBe(1);
-    expect(Utils.convertToInt(1.1)).toBe(1);
-    expect(Utils.convertToInt(1.9)).toBe(1);
-    expect(Utils.convertToInt(1.999)).toBe(1);
+    expect(convertToInt(undefined)).toBe(0);
+    expect(convertToInt(null)).toBe(0);
+    expect(convertToInt(0)).toBe(0);
+    const randomInteger = getRandomInteger();
+    expect(convertToInt(randomInteger)).toEqual(randomInteger);
+    expect(convertToInt('-1')).toBe(-1);
+    expect(convertToInt('1')).toBe(1);
+    expect(convertToInt('1.1')).toBe(1);
+    expect(convertToInt('1.9')).toBe(1);
+    expect(convertToInt('1.999')).toBe(1);
+    expect(convertToInt(-1)).toBe(-1);
+    expect(convertToInt(1)).toBe(1);
+    expect(convertToInt(1.1)).toBe(1);
+    expect(convertToInt(1.9)).toBe(1);
+    expect(convertToInt(1.999)).toBe(1);
     expect(() => {
-      Utils.convertToInt('NaN');
+      convertToInt('NaN');
     }).toThrow('Cannot convert to integer: NaN');
   });
 
   it('Verify convertToFloat()', () => {
-    expect(Utils.convertToFloat(undefined)).toBe(0);
-    expect(Utils.convertToFloat(null)).toBe(0);
-    expect(Utils.convertToFloat(0)).toBe(0);
-    const randomFloat = Utils.getRandomFloat();
-    expect(Utils.convertToFloat(randomFloat)).toEqual(randomFloat);
-    expect(Utils.convertToFloat('-1')).toBe(-1);
-    expect(Utils.convertToFloat('1')).toBe(1);
-    expect(Utils.convertToFloat('1.1')).toBe(1.1);
-    expect(Utils.convertToFloat('1.9')).toBe(1.9);
-    expect(Utils.convertToFloat('1.999')).toBe(1.999);
-    expect(Utils.convertToFloat(-1)).toBe(-1);
-    expect(Utils.convertToFloat(1)).toBe(1);
-    expect(Utils.convertToFloat(1.1)).toBe(1.1);
-    expect(Utils.convertToFloat(1.9)).toBe(1.9);
-    expect(Utils.convertToFloat(1.999)).toBe(1.999);
+    expect(convertToFloat(undefined)).toBe(0);
+    expect(convertToFloat(null)).toBe(0);
+    expect(convertToFloat(0)).toBe(0);
+    const randomFloat = getRandomFloat();
+    expect(convertToFloat(randomFloat)).toEqual(randomFloat);
+    expect(convertToFloat('-1')).toBe(-1);
+    expect(convertToFloat('1')).toBe(1);
+    expect(convertToFloat('1.1')).toBe(1.1);
+    expect(convertToFloat('1.9')).toBe(1.9);
+    expect(convertToFloat('1.999')).toBe(1.999);
+    expect(convertToFloat(-1)).toBe(-1);
+    expect(convertToFloat(1)).toBe(1);
+    expect(convertToFloat(1.1)).toBe(1.1);
+    expect(convertToFloat(1.9)).toBe(1.9);
+    expect(convertToFloat(1.999)).toBe(1.999);
     expect(() => {
-      Utils.convertToFloat('NaN');
+      convertToFloat('NaN');
     }).toThrow('Cannot convert to float: NaN');
   });
 
   it('Verify convertToBoolean()', () => {
-    expect(Utils.convertToBoolean(undefined)).toBe(false);
-    expect(Utils.convertToBoolean(null)).toBe(false);
-    expect(Utils.convertToBoolean('true')).toBe(true);
-    expect(Utils.convertToBoolean('false')).toBe(false);
-    expect(Utils.convertToBoolean('TRUE')).toBe(true);
-    expect(Utils.convertToBoolean('FALSE')).toBe(false);
-    expect(Utils.convertToBoolean('1')).toBe(true);
-    expect(Utils.convertToBoolean('0')).toBe(false);
-    expect(Utils.convertToBoolean(1)).toBe(true);
-    expect(Utils.convertToBoolean(0)).toBe(false);
-    expect(Utils.convertToBoolean(true)).toBe(true);
-    expect(Utils.convertToBoolean(false)).toBe(false);
-    expect(Utils.convertToBoolean('')).toBe(false);
-    expect(Utils.convertToBoolean('NoNBoolean')).toBe(false);
+    expect(convertToBoolean(undefined)).toBe(false);
+    expect(convertToBoolean(null)).toBe(false);
+    expect(convertToBoolean('true')).toBe(true);
+    expect(convertToBoolean('false')).toBe(false);
+    expect(convertToBoolean('TRUE')).toBe(true);
+    expect(convertToBoolean('FALSE')).toBe(false);
+    expect(convertToBoolean('1')).toBe(true);
+    expect(convertToBoolean('0')).toBe(false);
+    expect(convertToBoolean(1)).toBe(true);
+    expect(convertToBoolean(0)).toBe(false);
+    expect(convertToBoolean(true)).toBe(true);
+    expect(convertToBoolean(false)).toBe(false);
+    expect(convertToBoolean('')).toBe(false);
+    expect(convertToBoolean('NoNBoolean')).toBe(false);
   });
 
   it('Verify secureRandom()', () => {
-    const random = Utils.secureRandom();
+    const random = secureRandom();
     expect(typeof random === 'number').toBe(true);
     expect(random).toBeGreaterThanOrEqual(0);
     expect(random).toBeLessThan(1);
   });
 
   it('Verify getRandomInteger()', () => {
-    let randomInteger = Utils.getRandomInteger();
+    let randomInteger = getRandomInteger();
     expect(Number.isSafeInteger(randomInteger)).toBe(true);
     expect(randomInteger).toBeGreaterThanOrEqual(0);
     expect(randomInteger).toBeLessThanOrEqual(Constants.MAX_RANDOM_INTEGER);
-    expect(randomInteger).not.toEqual(Utils.getRandomInteger());
-    randomInteger = Utils.getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER);
+    expect(randomInteger).not.toEqual(getRandomInteger());
+    randomInteger = getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER);
     expect(randomInteger).toBeGreaterThanOrEqual(-Constants.MAX_RANDOM_INTEGER);
     expect(randomInteger).toBeLessThanOrEqual(0);
-    expect(() => Utils.getRandomInteger(0, 1)).toThrowError(
+    expect(() => getRandomInteger(0, 1)).toThrowError(
       'The value of "max" is out of range. It must be greater than the value of "min" (1). Received 1'
     );
-    expect(() => Utils.getRandomInteger(-1)).toThrowError(
+    expect(() => getRandomInteger(-1)).toThrowError(
       'The value of "max" is out of range. It must be greater than the value of "min" (0). Received 0'
     );
-    expect(() => Utils.getRandomInteger(Constants.MAX_RANDOM_INTEGER + 1)).toThrowError(
+    expect(() => getRandomInteger(Constants.MAX_RANDOM_INTEGER + 1)).toThrowError(
       `The value of "max" is out of range. It must be <= ${
         Constants.MAX_RANDOM_INTEGER + 1
       }. Received 281_474_976_710_656`
     );
-    randomInteger = Utils.getRandomInteger(2, 1);
+    randomInteger = getRandomInteger(2, 1);
     expect(randomInteger).toBeGreaterThanOrEqual(1);
     expect(randomInteger).toBeLessThanOrEqual(2);
     const max = 2.2,
       min = 1.1;
-    randomInteger = Utils.getRandomInteger(max, min);
+    randomInteger = getRandomInteger(max, min);
     expect(randomInteger).toBeGreaterThanOrEqual(Math.ceil(min));
     expect(randomInteger).toBeLessThanOrEqual(Math.floor(max));
   });
 
   it('Verify roundTo()', () => {
-    expect(Utils.roundTo(0, 2)).toBe(0);
-    expect(Utils.roundTo(0.5, 0)).toBe(1);
-    expect(Utils.roundTo(0.5, 2)).toBe(0.5);
-    expect(Utils.roundTo(-0.5, 0)).toBe(-1);
-    expect(Utils.roundTo(-0.5, 2)).toBe(-0.5);
-    expect(Utils.roundTo(1.005, 0)).toBe(1);
-    expect(Utils.roundTo(1.005, 2)).toBe(1.01);
-    expect(Utils.roundTo(2.175, 2)).toBe(2.18);
-    expect(Utils.roundTo(5.015, 2)).toBe(5.02);
-    expect(Utils.roundTo(-1.005, 2)).toBe(-1.01);
-    expect(Utils.roundTo(-2.175, 2)).toBe(-2.18);
-    expect(Utils.roundTo(-5.015, 2)).toBe(-5.02);
+    expect(roundTo(0, 2)).toBe(0);
+    expect(roundTo(0.5, 0)).toBe(1);
+    expect(roundTo(0.5, 2)).toBe(0.5);
+    expect(roundTo(-0.5, 0)).toBe(-1);
+    expect(roundTo(-0.5, 2)).toBe(-0.5);
+    expect(roundTo(1.005, 0)).toBe(1);
+    expect(roundTo(1.005, 2)).toBe(1.01);
+    expect(roundTo(2.175, 2)).toBe(2.18);
+    expect(roundTo(5.015, 2)).toBe(5.02);
+    expect(roundTo(-1.005, 2)).toBe(-1.01);
+    expect(roundTo(-2.175, 2)).toBe(-2.18);
+    expect(roundTo(-5.015, 2)).toBe(-5.02);
   });
 
   it('Verify getRandomFloat()', () => {
-    let randomFloat = Utils.getRandomFloat();
+    let randomFloat = getRandomFloat();
     expect(typeof randomFloat === 'number').toBe(true);
     expect(randomFloat).toBeGreaterThanOrEqual(0);
     expect(randomFloat).toBeLessThanOrEqual(Number.MAX_VALUE);
-    expect(randomFloat).not.toEqual(Utils.getRandomFloat());
-    expect(() => Utils.getRandomFloat(0, 1)).toThrowError(new RangeError('Invalid interval'));
-    expect(() => Utils.getRandomFloat(Number.MAX_VALUE, -Number.MAX_VALUE)).toThrowError(
+    expect(randomFloat).not.toEqual(getRandomFloat());
+    expect(() => getRandomFloat(0, 1)).toThrowError(new RangeError('Invalid interval'));
+    expect(() => getRandomFloat(Number.MAX_VALUE, -Number.MAX_VALUE)).toThrowError(
       new RangeError('Invalid interval')
     );
-    randomFloat = Utils.getRandomFloat(0, -Number.MAX_VALUE);
+    randomFloat = getRandomFloat(0, -Number.MAX_VALUE);
     expect(randomFloat).toBeGreaterThanOrEqual(-Number.MAX_VALUE);
     expect(randomFloat).toBeLessThanOrEqual(0);
   });
 
   it('Verify isObject()', () => {
-    expect(Utils.isObject('test')).toBe(false);
-    expect(Utils.isObject(undefined)).toBe(false);
-    expect(Utils.isObject(null)).toBe(false);
-    expect(Utils.isObject(0)).toBe(false);
-    expect(Utils.isObject([])).toBe(false);
-    expect(Utils.isObject([0, 1])).toBe(false);
-    expect(Utils.isObject(['0', '1'])).toBe(false);
-    expect(Utils.isObject({})).toBe(true);
-    expect(Utils.isObject({ 1: 1 })).toBe(true);
-    expect(Utils.isObject({ '1': '1' })).toBe(true);
-    expect(Utils.isObject(new Map())).toBe(true);
-    expect(Utils.isObject(new Set())).toBe(true);
-    expect(Utils.isObject(new WeakMap())).toBe(true);
-    expect(Utils.isObject(new WeakSet())).toBe(true);
+    expect(isObject('test')).toBe(false);
+    expect(isObject(undefined)).toBe(false);
+    expect(isObject(null)).toBe(false);
+    expect(isObject(0)).toBe(false);
+    expect(isObject([])).toBe(false);
+    expect(isObject([0, 1])).toBe(false);
+    expect(isObject(['0', '1'])).toBe(false);
+    expect(isObject({})).toBe(true);
+    expect(isObject({ 1: 1 })).toBe(true);
+    expect(isObject({ '1': '1' })).toBe(true);
+    expect(isObject(new Map())).toBe(true);
+    expect(isObject(new Set())).toBe(true);
+    expect(isObject(new WeakMap())).toBe(true);
+    expect(isObject(new WeakSet())).toBe(true);
   });
 
   it('Verify cloneObject()', () => {
     const obj = { 1: 1 };
-    expect(Utils.cloneObject(obj)).toStrictEqual(obj);
-    expect(Utils.cloneObject(obj) === obj).toBe(false);
+    expect(cloneObject(obj)).toStrictEqual(obj);
+    expect(cloneObject(obj) === obj).toBe(false);
     const array = [1, 2];
-    expect(Utils.cloneObject(array)).toStrictEqual(array);
-    expect(Utils.cloneObject(array) === array).toBe(false);
+    expect(cloneObject(array)).toStrictEqual(array);
+    expect(cloneObject(array) === array).toBe(false);
     const date = new Date();
-    expect(Utils.cloneObject(date)).toStrictEqual(date);
-    expect(Utils.cloneObject(date) === date).toBe(false);
+    expect(cloneObject(date)).toStrictEqual(date);
+    expect(cloneObject(date) === date).toBe(false);
     const map = new Map([['1', '2']]);
-    expect(Utils.cloneObject(map)).toStrictEqual(map);
-    expect(Utils.cloneObject(map) === map).toBe(false);
+    expect(cloneObject(map)).toStrictEqual(map);
+    expect(cloneObject(map) === map).toBe(false);
     const set = new Set(['1']);
-    expect(Utils.cloneObject(set)).toStrictEqual(set);
-    expect(Utils.cloneObject(set) === set).toBe(false);
+    expect(cloneObject(set)).toStrictEqual(set);
+    expect(cloneObject(set) === set).toBe(false);
     // The URL object seems to have not enumerable properties
     const url = new URL('https://domain.tld');
-    expect(Utils.cloneObject(url)).toStrictEqual(url);
-    expect(Utils.cloneObject(url) === url).toBe(true);
+    expect(cloneObject(url)).toStrictEqual(url);
+    expect(cloneObject(url) === url).toBe(true);
     const weakMap = new WeakMap([[{ 1: 1 }, { 2: 2 }]]);
-    expect(Utils.cloneObject(weakMap)).toStrictEqual(weakMap);
-    expect(Utils.cloneObject(weakMap) === weakMap).toBe(true);
+    expect(cloneObject(weakMap)).toStrictEqual(weakMap);
+    expect(cloneObject(weakMap) === weakMap).toBe(true);
     const weakSet = new WeakSet([{ 1: 1 }, { 2: 2 }]);
-    expect(Utils.cloneObject(weakSet)).toStrictEqual(weakSet);
-    expect(Utils.cloneObject(weakSet) === weakSet).toBe(true);
+    expect(cloneObject(weakSet)).toStrictEqual(weakSet);
+    expect(cloneObject(weakSet) === weakSet).toBe(true);
   });
 
   it('Verify hasOwnProp()', () => {
-    expect(Utils.hasOwnProp('test', '')).toBe(false);
-    expect(Utils.hasOwnProp(undefined, '')).toBe(false);
-    expect(Utils.hasOwnProp(null, '')).toBe(false);
-    expect(Utils.hasOwnProp([], '')).toBe(false);
-    expect(Utils.hasOwnProp({}, '')).toBe(false);
-    expect(Utils.hasOwnProp({ 1: 1 }, 1)).toBe(true);
-    expect(Utils.hasOwnProp({ 1: 1 }, '1')).toBe(true);
-    expect(Utils.hasOwnProp({ 1: 1 }, 2)).toBe(false);
-    expect(Utils.hasOwnProp({ 1: 1 }, '2')).toBe(false);
-    expect(Utils.hasOwnProp({ '1': '1' }, '1')).toBe(true);
-    expect(Utils.hasOwnProp({ '1': '1' }, 1)).toBe(true);
-    expect(Utils.hasOwnProp({ '1': '1' }, '2')).toBe(false);
-    expect(Utils.hasOwnProp({ '1': '1' }, 2)).toBe(false);
+    expect(hasOwnProp('test', '')).toBe(false);
+    expect(hasOwnProp(undefined, '')).toBe(false);
+    expect(hasOwnProp(null, '')).toBe(false);
+    expect(hasOwnProp([], '')).toBe(false);
+    expect(hasOwnProp({}, '')).toBe(false);
+    expect(hasOwnProp({ 1: 1 }, 1)).toBe(true);
+    expect(hasOwnProp({ 1: 1 }, '1')).toBe(true);
+    expect(hasOwnProp({ 1: 1 }, 2)).toBe(false);
+    expect(hasOwnProp({ 1: 1 }, '2')).toBe(false);
+    expect(hasOwnProp({ '1': '1' }, '1')).toBe(true);
+    expect(hasOwnProp({ '1': '1' }, 1)).toBe(true);
+    expect(hasOwnProp({ '1': '1' }, '2')).toBe(false);
+    expect(hasOwnProp({ '1': '1' }, 2)).toBe(false);
   });
 
   it('Verify isIterable()', () => {
-    expect(Utils.isIterable('')).toBe(true);
-    expect(Utils.isIterable(' ')).toBe(true);
-    expect(Utils.isIterable('test')).toBe(true);
-    expect(Utils.isIterable(undefined)).toBe(false);
-    expect(Utils.isIterable(null)).toBe(false);
-    expect(Utils.isIterable(0)).toBe(false);
-    expect(Utils.isIterable([0, 1])).toBe(true);
-    expect(Utils.isIterable({ 1: 1 })).toBe(false);
-    expect(Utils.isIterable(new Map())).toBe(true);
-    expect(Utils.isIterable(new Set())).toBe(true);
-    expect(Utils.isIterable(new WeakMap())).toBe(false);
-    expect(Utils.isIterable(new WeakSet())).toBe(false);
+    expect(isIterable('')).toBe(true);
+    expect(isIterable(' ')).toBe(true);
+    expect(isIterable('test')).toBe(true);
+    expect(isIterable(undefined)).toBe(false);
+    expect(isIterable(null)).toBe(false);
+    expect(isIterable(0)).toBe(false);
+    expect(isIterable([0, 1])).toBe(true);
+    expect(isIterable({ 1: 1 })).toBe(false);
+    expect(isIterable(new Map())).toBe(true);
+    expect(isIterable(new Set())).toBe(true);
+    expect(isIterable(new WeakMap())).toBe(false);
+    expect(isIterable(new WeakSet())).toBe(false);
   });
 
   it('Verify isEmptyString()', () => {
-    expect(Utils.isEmptyString('')).toBe(true);
-    expect(Utils.isEmptyString(' ')).toBe(true);
-    expect(Utils.isEmptyString('     ')).toBe(true);
-    expect(Utils.isEmptyString('test')).toBe(false);
-    expect(Utils.isEmptyString(' test')).toBe(false);
-    expect(Utils.isEmptyString('test ')).toBe(false);
-    expect(Utils.isEmptyString(undefined)).toBe(true);
-    expect(Utils.isEmptyString(null)).toBe(true);
-    expect(Utils.isEmptyString(0)).toBe(false);
-    expect(Utils.isEmptyString({})).toBe(false);
-    expect(Utils.isEmptyString([])).toBe(false);
-    expect(Utils.isEmptyString(new Map())).toBe(false);
-    expect(Utils.isEmptyString(new Set())).toBe(false);
-    expect(Utils.isEmptyString(new WeakMap())).toBe(false);
-    expect(Utils.isEmptyString(new WeakSet())).toBe(false);
+    expect(isEmptyString('')).toBe(true);
+    expect(isEmptyString(' ')).toBe(true);
+    expect(isEmptyString('     ')).toBe(true);
+    expect(isEmptyString('test')).toBe(false);
+    expect(isEmptyString(' test')).toBe(false);
+    expect(isEmptyString('test ')).toBe(false);
+    expect(isEmptyString(undefined)).toBe(true);
+    expect(isEmptyString(null)).toBe(true);
+    expect(isEmptyString(0)).toBe(false);
+    expect(isEmptyString({})).toBe(false);
+    expect(isEmptyString([])).toBe(false);
+    expect(isEmptyString(new Map())).toBe(false);
+    expect(isEmptyString(new Set())).toBe(false);
+    expect(isEmptyString(new WeakMap())).toBe(false);
+    expect(isEmptyString(new WeakSet())).toBe(false);
   });
 
   it('Verify isNotEmptyString()', () => {
-    expect(Utils.isNotEmptyString('')).toBe(false);
-    expect(Utils.isNotEmptyString(' ')).toBe(false);
-    expect(Utils.isNotEmptyString('     ')).toBe(false);
-    expect(Utils.isNotEmptyString('test')).toBe(true);
-    expect(Utils.isNotEmptyString(' test')).toBe(true);
-    expect(Utils.isNotEmptyString('test ')).toBe(true);
-    expect(Utils.isNotEmptyString(undefined)).toBe(false);
-    expect(Utils.isNotEmptyString(null)).toBe(false);
-    expect(Utils.isNotEmptyString(0)).toBe(false);
-    expect(Utils.isNotEmptyString({})).toBe(false);
-    expect(Utils.isNotEmptyString([])).toBe(false);
-    expect(Utils.isNotEmptyString(new Map())).toBe(false);
-    expect(Utils.isNotEmptyString(new Set())).toBe(false);
-    expect(Utils.isNotEmptyString(new WeakMap())).toBe(false);
-    expect(Utils.isNotEmptyString(new WeakSet())).toBe(false);
+    expect(isNotEmptyString('')).toBe(false);
+    expect(isNotEmptyString(' ')).toBe(false);
+    expect(isNotEmptyString('     ')).toBe(false);
+    expect(isNotEmptyString('test')).toBe(true);
+    expect(isNotEmptyString(' test')).toBe(true);
+    expect(isNotEmptyString('test ')).toBe(true);
+    expect(isNotEmptyString(undefined)).toBe(false);
+    expect(isNotEmptyString(null)).toBe(false);
+    expect(isNotEmptyString(0)).toBe(false);
+    expect(isNotEmptyString({})).toBe(false);
+    expect(isNotEmptyString([])).toBe(false);
+    expect(isNotEmptyString(new Map())).toBe(false);
+    expect(isNotEmptyString(new Set())).toBe(false);
+    expect(isNotEmptyString(new WeakMap())).toBe(false);
+    expect(isNotEmptyString(new WeakSet())).toBe(false);
   });
 
   it('Verify isUndefined()', () => {
-    expect(Utils.isUndefined(undefined)).toBe(true);
-    expect(Utils.isUndefined(null)).toBe(false);
-    expect(Utils.isUndefined('')).toBe(false);
-    expect(Utils.isUndefined(0)).toBe(false);
-    expect(Utils.isUndefined({})).toBe(false);
-    expect(Utils.isUndefined([])).toBe(false);
-    expect(Utils.isUndefined(new Map())).toBe(false);
-    expect(Utils.isUndefined(new Set())).toBe(false);
-    expect(Utils.isUndefined(new WeakMap())).toBe(false);
-    expect(Utils.isUndefined(new WeakSet())).toBe(false);
+    expect(isUndefined(undefined)).toBe(true);
+    expect(isUndefined(null)).toBe(false);
+    expect(isUndefined('')).toBe(false);
+    expect(isUndefined(0)).toBe(false);
+    expect(isUndefined({})).toBe(false);
+    expect(isUndefined([])).toBe(false);
+    expect(isUndefined(new Map())).toBe(false);
+    expect(isUndefined(new Set())).toBe(false);
+    expect(isUndefined(new WeakMap())).toBe(false);
+    expect(isUndefined(new WeakSet())).toBe(false);
   });
 
   it('Verify isNullOrUndefined()', () => {
-    expect(Utils.isNullOrUndefined(undefined)).toBe(true);
-    expect(Utils.isNullOrUndefined(null)).toBe(true);
-    expect(Utils.isNullOrUndefined('')).toBe(false);
-    expect(Utils.isNullOrUndefined(0)).toBe(false);
-    expect(Utils.isNullOrUndefined({})).toBe(false);
-    expect(Utils.isNullOrUndefined([])).toBe(false);
-    expect(Utils.isNullOrUndefined(new Map())).toBe(false);
-    expect(Utils.isNullOrUndefined(new Set())).toBe(false);
-    expect(Utils.isNullOrUndefined(new WeakMap())).toBe(false);
-    expect(Utils.isNullOrUndefined(new WeakSet())).toBe(false);
+    expect(isNullOrUndefined(undefined)).toBe(true);
+    expect(isNullOrUndefined(null)).toBe(true);
+    expect(isNullOrUndefined('')).toBe(false);
+    expect(isNullOrUndefined(0)).toBe(false);
+    expect(isNullOrUndefined({})).toBe(false);
+    expect(isNullOrUndefined([])).toBe(false);
+    expect(isNullOrUndefined(new Map())).toBe(false);
+    expect(isNullOrUndefined(new Set())).toBe(false);
+    expect(isNullOrUndefined(new WeakMap())).toBe(false);
+    expect(isNullOrUndefined(new WeakSet())).toBe(false);
   });
 
   it('Verify isEmptyArray()', () => {
-    expect(Utils.isEmptyArray([])).toBe(true);
-    expect(Utils.isEmptyArray([1, 2])).toBe(false);
-    expect(Utils.isEmptyArray(['1', '2'])).toBe(false);
-    expect(Utils.isEmptyArray(undefined)).toBe(false);
-    expect(Utils.isEmptyArray(null)).toBe(false);
-    expect(Utils.isEmptyArray('')).toBe(false);
-    expect(Utils.isEmptyArray('test')).toBe(false);
-    expect(Utils.isEmptyArray(0)).toBe(false);
-    expect(Utils.isEmptyArray({})).toBe(false);
-    expect(Utils.isEmptyArray(new Map())).toBe(false);
-    expect(Utils.isEmptyArray(new Set())).toBe(false);
-    expect(Utils.isEmptyArray(new WeakMap())).toBe(false);
-    expect(Utils.isEmptyArray(new WeakSet())).toBe(false);
+    expect(isEmptyArray([])).toBe(true);
+    expect(isEmptyArray([1, 2])).toBe(false);
+    expect(isEmptyArray(['1', '2'])).toBe(false);
+    expect(isEmptyArray(undefined)).toBe(false);
+    expect(isEmptyArray(null)).toBe(false);
+    expect(isEmptyArray('')).toBe(false);
+    expect(isEmptyArray('test')).toBe(false);
+    expect(isEmptyArray(0)).toBe(false);
+    expect(isEmptyArray({})).toBe(false);
+    expect(isEmptyArray(new Map())).toBe(false);
+    expect(isEmptyArray(new Set())).toBe(false);
+    expect(isEmptyArray(new WeakMap())).toBe(false);
+    expect(isEmptyArray(new WeakSet())).toBe(false);
   });
 
   it('Verify isNotEmptyArray()', () => {
-    expect(Utils.isNotEmptyArray([])).toBe(false);
-    expect(Utils.isNotEmptyArray([1, 2])).toBe(true);
-    expect(Utils.isNotEmptyArray(['1', '2'])).toBe(true);
-    expect(Utils.isNotEmptyArray(undefined)).toBe(false);
-    expect(Utils.isNotEmptyArray(null)).toBe(false);
-    expect(Utils.isNotEmptyArray('')).toBe(false);
-    expect(Utils.isNotEmptyArray('test')).toBe(false);
-    expect(Utils.isNotEmptyArray(0)).toBe(false);
-    expect(Utils.isNotEmptyArray({})).toBe(false);
-    expect(Utils.isNotEmptyArray(new Map())).toBe(false);
-    expect(Utils.isNotEmptyArray(new Set())).toBe(false);
-    expect(Utils.isNotEmptyArray(new WeakMap())).toBe(false);
-    expect(Utils.isNotEmptyArray(new WeakSet())).toBe(false);
+    expect(isNotEmptyArray([])).toBe(false);
+    expect(isNotEmptyArray([1, 2])).toBe(true);
+    expect(isNotEmptyArray(['1', '2'])).toBe(true);
+    expect(isNotEmptyArray(undefined)).toBe(false);
+    expect(isNotEmptyArray(null)).toBe(false);
+    expect(isNotEmptyArray('')).toBe(false);
+    expect(isNotEmptyArray('test')).toBe(false);
+    expect(isNotEmptyArray(0)).toBe(false);
+    expect(isNotEmptyArray({})).toBe(false);
+    expect(isNotEmptyArray(new Map())).toBe(false);
+    expect(isNotEmptyArray(new Set())).toBe(false);
+    expect(isNotEmptyArray(new WeakMap())).toBe(false);
+    expect(isNotEmptyArray(new WeakSet())).toBe(false);
   });
 
   it('Verify isEmptyObject()', () => {
-    expect(Utils.isEmptyObject({})).toBe(true);
-    expect(Utils.isEmptyObject({ 1: 1, 2: 2 })).toBe(false);
-    expect(Utils.isEmptyObject(undefined)).toBe(false);
-    expect(Utils.isEmptyObject(null)).toBe(false);
-    expect(Utils.isEmptyObject(new Map())).toBe(false);
-    expect(Utils.isEmptyObject(new Set())).toBe(false);
-    expect(Utils.isEmptyObject(new WeakMap())).toBe(false);
-    expect(Utils.isEmptyObject(new WeakSet())).toBe(false);
+    expect(isEmptyObject({})).toBe(true);
+    expect(isEmptyObject({ 1: 1, 2: 2 })).toBe(false);
+    expect(isEmptyObject(undefined)).toBe(false);
+    expect(isEmptyObject(null)).toBe(false);
+    expect(isEmptyObject(new Map())).toBe(false);
+    expect(isEmptyObject(new Set())).toBe(false);
+    expect(isEmptyObject(new WeakMap())).toBe(false);
+    expect(isEmptyObject(new WeakSet())).toBe(false);
   });
 });