]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor: use string/array helper functions consistently
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 3 Apr 2026 14:27:05 +0000 (16:27 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 3 Apr 2026 14:27:05 +0000 (16:27 +0200)
Replace 9 manual .trim().length checks with isEmpty() and
isNotEmptyString() helpers. Replace Array.isArray+length
guards with isNotEmptyArray() in StatisticUtils. Simplify
isValidIdentifierValue to delegate to isNotEmptyString.
Replace hardcoded SecurityCtrlr.OrganizationName string
with OCPP20ComponentName/RequiredVariableName enums.

src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts
src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts
src/charging-station/ocpp/2.0/OCPP20RequestService.ts
src/charging-station/ocpp/2.0/OCPP20VariableRegistry.ts
src/charging-station/ocpp/auth/utils/AuthValidators.ts
src/utils/Configuration.ts
src/utils/ConfigurationMigration.ts
src/utils/StatisticUtils.ts

index a81e88570dc25eaabc73650c710c7a7ec94e4892..9468f1b6edce3862700323110512e2032f191215 100644 (file)
@@ -16,7 +16,7 @@ import {
   HashAlgorithmEnumType,
   InstallCertificateUseEnumType,
 } from '../../../types/index.js'
-import { convertToDate, getErrorMessage } from '../../../utils/index.js'
+import { convertToDate, getErrorMessage, isEmpty } from '../../../utils/index.js'
 
 /**
  * Interface for ChargingStation with certificate manager
@@ -439,7 +439,7 @@ export class OCPP20CertificateManager {
       return false
     }
 
-    if (pemData.trim().length === 0) {
+    if (isEmpty(pemData)) {
       return false
     }
 
index 03c3d3f6bc22aaff405a510994222f906d1d7ab5..a175e806752719eabd5452d916db9c6dc16fcde6 100644 (file)
@@ -131,6 +131,8 @@ import {
   convertToDate,
   convertToIntOrNaN,
   generateUUID,
+  isEmpty,
+  isNotEmptyString,
   logger,
   promiseWithTimeout,
   sleep,
@@ -2815,7 +2817,7 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
     )
 
     // C10: Validate signing certificate PEM format if present
-    if (firmware.signingCertificate != null && firmware.signingCertificate.trim() !== '') {
+    if (isNotEmptyString(firmware.signingCertificate)) {
       if (
         !hasCertificateManager(chargingStation) ||
         !chargingStation.certificateManager.validateCertificateFormat(firmware.signingCertificate)
@@ -3478,7 +3480,7 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
     if (checkAborted()) return
 
     // H9: If firmware location is empty or malformed, send DownloadFailed and stop
-    if (location.trim() === '' || !this.isValidFirmwareLocation(location)) {
+    if (isEmpty(location) || !this.isValidFirmwareLocation(location)) {
       // L01.FR.30: Simulate download retries before reporting DownloadFailed
       const maxRetries = retries ?? 0
       const retryDelayMs = secondsToMilliseconds(retryInterval ?? 0)
index ab9640e07dbbfc73e58ccbb9c99af441c71bfdf1..980aecb0e2b3eb8f96e7ed6a1ba5b3e350e737dd 100644 (file)
@@ -10,7 +10,9 @@ import {
   ErrorType,
   type JsonObject,
   type JsonType,
+  OCPP20ComponentName,
   OCPP20RequestCommand,
+  OCPP20RequiredVariableName,
   type OCPP20SignCertificateRequest,
   type OCPP20StatusNotificationRequest,
   type OCPP20TransactionEventOptions,
@@ -168,7 +170,10 @@ export class OCPP20RequestService extends OCPPRequestService {
       case OCPP20RequestCommand.SIGN_CERTIFICATE: {
         let csr: string
         try {
-          const configKey = getConfigurationKey(chargingStation, 'SecurityCtrlr.OrganizationName')
+          const configKey = getConfigurationKey(
+            chargingStation,
+            `${OCPP20ComponentName.SecurityCtrlr}.${OCPP20RequiredVariableName.OrganizationName}`
+          )
           const orgName = configKey?.value ?? 'Unknown'
           const stationId = chargingStation.stationInfo?.chargingStationId ?? 'Unknown'
 
index cb9698b4139422b6ed2e26e5feb03cb74fca3152..f8819f8c446d5e94df5e949006f6b0c40459c9b7 100644 (file)
@@ -22,7 +22,7 @@ import {
   ReasonCodeEnumType,
   type VariableName,
 } from '../../../types/index.js'
-import { Constants, convertToIntOrNaN, has } from '../../../utils/index.js'
+import { Constants, convertToIntOrNaN, has, isEmpty } from '../../../utils/index.js'
 import { OCPP20Constants } from './OCPP20Constants.js'
 
 /**
@@ -2697,7 +2697,7 @@ export function validateValue (
     }
     case DataEnumType.MemberList:
     case DataEnumType.SequenceList: {
-      if (rawValue.trim().length === 0) {
+      if (isEmpty(rawValue)) {
         return { info: 'List cannot be empty', ok: false, reason: ReasonCodeEnumType.InvalidValue }
       }
       if (rawValue.startsWith(',') || rawValue.endsWith(',')) {
index f3b238a54935b7a8ef484c7853c5e25dc2f07649..1961bf6a1f25ef6ee1e3c84b8d08f319f0eb01fc 100644 (file)
@@ -1,5 +1,6 @@
 import type { AuthConfiguration, Identifier } from '../types/AuthTypes.js'
 
+import { isNotEmptyString } from '../../../../utils/index.js'
 import { IdentifierType } from '../types/AuthTypes.js'
 
 /**
@@ -51,12 +52,7 @@ function isValidConnectorId (connectorId: number | undefined): boolean {
  * @returns True if the value is a non-empty string with at least one non-whitespace character, false otherwise
  */
 function isValidIdentifierValue (value: string): boolean {
-  if (typeof value !== 'string' || value.length === 0) {
-    return false
-  }
-
-  // Must contain at least one non-whitespace character
-  return value.trim().length > 0
+  return isNotEmptyString(value)
 }
 
 /**
index 0c706ac71d34da943a3bb757ba998d92643a3ec5..27f2604e8678e6a88b8a9eec0fa5df8001577914 100644 (file)
@@ -35,7 +35,7 @@ import {
 } from './ConfigurationUtils.js'
 import { Constants } from './Constants.js'
 import { ensureError, handleFileException } from './ErrorUtils.js'
-import { has, isCFEnvironment, mergeDeepRight, once } from './Utils.js'
+import { has, isCFEnvironment, isNotEmptyString, mergeDeepRight, once } from './Utils.js'
 
 type ConfigurationSectionType =
   | LogConfiguration
@@ -130,8 +130,7 @@ export class Configuration {
   public static getConfigurationData (): ConfigurationData | undefined {
     if (
       Configuration.configurationData == null &&
-      Configuration.configurationFile != null &&
-      Configuration.configurationFile.trim().length > 0
+      isNotEmptyString(Configuration.configurationFile)
     ) {
       try {
         Configuration.configurationData = JSON.parse(
@@ -353,10 +352,7 @@ export class Configuration {
   }
 
   private static getConfigurationFileWatcher (): FSWatcher | undefined {
-    if (
-      Configuration.configurationFile == null ||
-      Configuration.configurationFile.trim().length === 0
-    ) {
+    if (!isNotEmptyString(Configuration.configurationFile)) {
       return
     }
     try {
index 65f34d325b14f5cf59c5842a4a90c644ecf6f0db..50dbcd3276536bbedcfec8864b30e696cca6c070 100644 (file)
@@ -7,7 +7,7 @@ import {
 } from '../types/index.js'
 import { WorkerProcessType } from '../worker/index.js'
 import { logPrefix } from './ConfigurationUtils.js'
-import { has } from './Utils.js'
+import { has, isNotEmptyString } from './Utils.js'
 
 /**
  * Check and warn about deprecated configuration keys
@@ -198,7 +198,7 @@ function warnDeprecatedConfigurationKey (
     console.error(
       `${chalk.green(logPrefix())} ${chalk.red(
         `Deprecated configuration key '${key}' usage in section '${configurationSection}'${
-          logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
+          isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
         }`
       )}`
     )
@@ -206,7 +206,7 @@ function warnDeprecatedConfigurationKey (
     console.error(
       `${chalk.green(logPrefix())} ${chalk.red(
         `Deprecated configuration key '${key}' usage${
-          logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
+          isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
         }`
       )}`
     )
index 759660643b4fc8e6a5641263bf547b70285f8ddd..f835e517798e5b34e214a1c18495338daf3d6ff5 100644 (file)
@@ -1,5 +1,7 @@
+import { isNotEmptyArray } from './Utils.js'
+
 export const average = (dataSet: number[]): number => {
-  if (!Array.isArray(dataSet) || dataSet.length === 0) {
+  if (!isNotEmptyArray<number>(dataSet)) {
     return 0
   }
   if (dataSet.length === 1) {
@@ -9,7 +11,7 @@ export const average = (dataSet: number[]): number => {
 }
 
 export const median = (dataSet: number[]): number => {
-  if (!Array.isArray(dataSet) || dataSet.length === 0) {
+  if (!isNotEmptyArray<number>(dataSet)) {
     return 0
   }
   if (dataSet.length === 1) {