From 9bf0ef23c51160abc6866ad8d07eea85e308edb8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 5 Jul 2023 16:43:08 +0200 Subject: [PATCH] refactor: split Utils static methods class into functions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../AutomaticTransactionGenerator.ts | 42 +- src/charging-station/Bootstrap.ts | 16 +- src/charging-station/ChargingStation.ts | 137 ++-- src/charging-station/ChargingStationUtils.ts | 98 +-- src/charging-station/IdTagsCache.ts | 17 +- src/charging-station/SharedLRUCache.ts | 19 +- .../ChargingStationWorkerBroadcastChannel.ts | 15 +- .../UIServiceWorkerBroadcastChannel.ts | 8 +- .../WorkerBroadcastChannel.ts | 6 +- .../ocpp/1.6/OCPP16IncomingRequestService.ts | 62 +- .../ocpp/1.6/OCPP16RequestService.ts | 4 +- .../ocpp/1.6/OCPP16ResponseService.ts | 18 +- .../ocpp/1.6/OCPP16ServiceUtils.ts | 145 +++-- .../ocpp/2.0/OCPP20RequestService.ts | 4 +- .../ocpp/OCPPRequestService.ts | 14 +- src/charging-station/ocpp/OCPPServiceUtils.ts | 14 +- .../ui-server/UIHttpServer.ts | 17 +- .../ui-server/UIServerUtils.ts | 4 +- .../ui-server/UIWebSocketServer.ts | 20 +- .../ui-services/AbstractUIService.ts | 10 +- src/performance/PerformanceStatistics.ts | 17 +- src/performance/storage/JsonFileStorage.ts | 17 +- src/performance/storage/Storage.ts | 4 +- .../ChargingStationConfigurationUtils.ts | 6 +- src/utils/Configuration.ts | 69 +- src/utils/ErrorUtils.ts | 4 +- src/utils/FileUtils.ts | 6 +- src/utils/Logger.ts | 6 +- src/utils/StatisticUtils.ts | 8 +- src/utils/Utils.ts | 602 +++++++++--------- src/utils/index.ts | 30 +- test/utils/Utils.test.ts | 473 +++++++------- 32 files changed, 1023 insertions(+), 889 deletions(-) diff --git a/src/charging-station/AutomaticTransactionGenerator.ts b/src/charging-station/AutomaticTransactionGenerator.ts index 0389526f..233f2519 100644 --- a/src/charging-station/AutomaticTransactionGenerator.ts +++ b/src/charging-station/AutomaticTransactionGenerator.ts @@ -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()}` : '' }:` ); }; diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 8a3f9078..cb4b65eb 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -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((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 |'); }; } diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index fd974556..af021085 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -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 { 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)); + this.connectors.set(connectorId, cloneObject(connectorStatus)); } } else if (configuration?.evsesStatus && !configuration?.connectorsStatus) { for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) { - const evseStatus = Utils.cloneObject(evseStatusConfiguration); + const evseStatus = cloneObject(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)); + this.connectors.set(connectorId, cloneObject(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(this.getConfigurationFromFile()) ?? {}; + cloneObject(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()}` ); diff --git a/src/charging-station/ChargingStationUtils.ts b/src/charging-station/ChargingStationUtils.ts index ab781fae..3e5d658d 100644 --- a/src/charging-station/ChargingStationUtils.ts +++ b/src/charging-station/ChargingStationUtils.ts @@ -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)); + connectorsMap.set(connectorId, cloneObject(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(stationTemplate); + stationTemplate = cloneObject(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( + cloneObject( 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( + ...cloneObject( 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]; } diff --git a/src/charging-station/IdTagsCache.ts b/src/charging-station/IdTagsCache.ts index c0f4d2b9..0b3ba285 100644 --- a/src/charging-station/IdTagsCache.ts +++ b/src/charging-station/IdTagsCache.ts @@ -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}' |`); }; } diff --git a/src/charging-station/SharedLRUCache.ts b/src/charging-station/SharedLRUCache.ts index ba0a47d5..57845313 100644 --- a/src/charging-station/SharedLRUCache.ts +++ b/src/charging-station/SharedLRUCache.ts @@ -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 ); } } diff --git a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts index b2828305..9eb69cd3 100644 --- a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts +++ b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts @@ -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; diff --git a/src/charging-station/broadcast-channel/UIServiceWorkerBroadcastChannel.ts b/src/charging-station/broadcast-channel/UIServiceWorkerBroadcastChannel.ts index b66cd8a0..548b3147 100644 --- a/src/charging-station/broadcast-channel/UIServiceWorkerBroadcastChannel.ts +++ b/src/charging-station/broadcast-channel/UIServiceWorkerBroadcastChannel.ts @@ -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; diff --git a/src/charging-station/broadcast-channel/WorkerBroadcastChannel.ts b/src/charging-station/broadcast-channel/WorkerBroadcastChannel.ts index fd73b1bb..9168764d 100644 --- a/src/charging-station/broadcast-channel/WorkerBroadcastChannel.ts +++ b/src/charging-station/broadcast-channel/WorkerBroadcastChannel.ts @@ -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}:`); }; } diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 73943d4e..6e0b57be 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -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( chargingStation, diff --git a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts index 7ff1fdb8..fb500724 100644 --- a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts @@ -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(chargingStation, commandName, commandParams), commandName, params diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index 5d87f633..fae1dd9c 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -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); diff --git a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts index 4ddeed55..aac11154 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts @@ -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) diff --git a/src/charging-station/ocpp/2.0/OCPP20RequestService.ts b/src/charging-station/ocpp/2.0/OCPP20RequestService.ts index 6e857089..15a3b502 100644 --- a/src/charging-station/ocpp/2.0/OCPP20RequestService.ts +++ b/src/charging-station/ocpp/2.0/OCPP20RequestService.ts @@ -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(chargingStation, commandName, commandParams), commandName, params diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index a3b78ca6..443c6c80 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -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(payload); + payload = cloneObject(payload); OCPPServiceUtils.convertDateToISOString(payload); if (validate(payload)) { return true; @@ -242,7 +248,7 @@ export abstract class OCPPRequestService { commandName as IncomingRequestCommand ) ); - payload = Utils.cloneObject(payload); + payload = cloneObject(payload); OCPPServiceUtils.convertDateToISOString(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 diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index 7433f71d..8e206490 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -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); }; } diff --git a/src/charging-station/ui-server/UIHttpServer.ts b/src/charging-station/ui-server/UIHttpServer.ts index 159559df..97eaa119 100644 --- a/src/charging-station/ui-server/UIHttpServer.ts +++ b/src/charging-station/ui-server/UIHttpServer.ts @@ -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); } }) diff --git a/src/charging-station/ui-server/UIServerUtils.ts b/src/charging-station/ui-server/UIServerUtils.ts index 056d31fa..cada1399 100644 --- a/src/charging-station/ui-server/UIServerUtils.ts +++ b/src/charging-station/ui-server/UIServerUtils.ts @@ -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}` ); diff --git a/src/charging-station/ui-server/UIWebSocketServer.ts b/src/charging-station/ui-server/UIWebSocketServer.ts index 09842bf6..2cd0267c 100644 --- a/src/charging-station/ui-server/UIWebSocketServer.ts +++ b/src/charging-station/ui-server/UIWebSocketServer.ts @@ -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, diff --git a/src/charging-station/ui-server/ui-services/AbstractUIService.ts b/src/charging-station/ui-server/ui-services/AbstractUIService.ts index 1ec6cf93..bfe3751c 100644 --- a/src/charging-station/ui-server/ui-services/AbstractUIService.ts +++ b/src/charging-station/ui-server/ui-services/AbstractUIService.ts @@ -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]); diff --git a/src/performance/PerformanceStatistics.ts b/src/performance/PerformanceStatistics.ts index 80f53e54..2733fd74 100644 --- a/src/performance/PerformanceStatistics.ts +++ b/src/performance/PerformanceStatistics.ts @@ -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`); }; } diff --git a/src/performance/storage/JsonFileStorage.ts b/src/performance/storage/JsonFileStorage.ts index e1a9a44e..c4a9f748 100644 --- a/src/performance/storage/JsonFileStorage.ts +++ b/src/performance/storage/JsonFileStorage.ts @@ -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 }); } diff --git a/src/performance/storage/Storage.ts b/src/performance/storage/Storage.ts index 1360dabb..f0fda133 100644 --- a/src/performance/storage/Storage.ts +++ b/src/performance/storage/Storage.ts @@ -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 diff --git a/src/utils/ChargingStationConfigurationUtils.ts b/src/utils/ChargingStationConfigurationUtils.ts index e61730c7..d264afec 100644 --- a/src/utils/ChargingStationConfigurationUtils.ts +++ b/src/utils/ChargingStationConfigurationUtils.ts @@ -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(), ], diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index e115aeb3..e5f8a7c0 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -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, 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)[key]) + !isUndefined(Configuration.getConfig()[sectionName]) && + !isUndefined((Configuration.getConfig()[sectionName] as Record)[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': diff --git a/src/utils/ErrorUtils.ts b/src/utils/ErrorUtils.ts index b4f52ba8..0e3dbc50 100644 --- a/src/utils/ErrorUtils.ts +++ b/src/utils/ErrorUtils.ts @@ -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 = defaultErrorParams ): void => { setDefaultErrorParams(params); - const prefix = Utils.isNotEmptyString(logPrefix) ? `${logPrefix} ` : ''; + const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : ''; let logMsg: string; switch (error.code) { case 'ENOENT': diff --git a/src/utils/FileUtils.ts b/src/utils/FileUtils.ts index 5e40b724..d1d5d629 100644 --- a/src/utils/FileUtils.ts +++ b/src/utils/FileUtils.ts @@ -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 = ( @@ -11,7 +11,7 @@ export const watchJsonFile = ( logPrefix: string, refreshedVariable?: T, listener: WatchListener = (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 = ( } } ): FSWatcher | undefined => { - if (Utils.isNotEmptyString(file)) { + if (isNotEmptyString(file)) { try { return watch(file, listener); } catch (error) { diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts index 92fe6909..3f94e63e 100644 --- a/src/utils/Logger.ts +++ b/src/utils/Logger.ts @@ -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') diff --git a/src/utils/StatisticUtils.ts b/src/utils/StatisticUtils.ts index bb9a8470..a2d906eb 100644 --- a/src/utils/StatisticUtils.ts +++ b/src/utils/StatisticUtils.ts @@ -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) * diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 7b0c9239..f15224a8 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -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 => { + return new Promise((resolve) => setTimeout(resolve as () => void, milliSeconds)); +}; - public static async sleep(milliSeconds: number): Promise { - 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(object: T): T { - return clone(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(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): boolean { - return inspect(promise).includes('pending'); - } - - public static async promiseWithTimeout( - promise: Promise, - 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 { - // Create a timeout promise that rejects in timeout milliseconds - const timeoutPromise = new Promise((_, 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([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 | Record[] | Map, - space?: number - ): string { - return JSON.stringify( - obj, - (key, value: Record) => { - 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 = (object: T): T => { + return clone(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 = (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): boolean => { + return inspect(promise).includes('pending'); +}; + +export const promiseWithTimeout = async ( + promise: Promise, + timeoutMs: number, + timeoutError: Error, + timeoutCallback: () => void = () => { + /* This is intentional */ + } +): Promise => { + // Create a timeout promise that rejects in timeout milliseconds + const timeoutPromise = new Promise((_, 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([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 | Record[] | Map, + space?: number +): string => { + return JSON.stringify( + obj, + (key, value: Record) => { + 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)'; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index b2374d73..93eae31e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -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'; diff --git a/test/utils/Utils.test.ts b/test/utils/Utils.test.ts index 60d2e2ae..892f25a5 100644 --- a/test/utils/Utils.test.ts +++ b/test/utils/Utils.test.ts @@ -1,347 +1,370 @@ 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); }); }); -- 2.34.1