]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor: audit-driven improvements — use BaseError, fix barrel bypass, remove redund... main
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 24 Mar 2026 14:51:21 +0000 (15:51 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 24 Mar 2026 14:51:21 +0000 (15:51 +0100)
- Replace throw new Error with BaseError in OCPP20CertificateManager and
  OCPP20VariableManager (3 occurrences)
- Move getMessageTypeString from OCPPServiceUtils to Helpers, resolving
  the barrel bypass in ErrorUtils — consumers import via charging-station
  barrel, tests moved to Helpers.test.ts
- Remove redundant console.warn in Helpers (logger.warn already called)
- Remove unused chalk import from Helpers

src/charging-station/ChargingStation.ts
src/charging-station/Helpers.ts
src/charging-station/index.ts
src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts
src/charging-station/ocpp/2.0/OCPP20VariableManager.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/charging-station/ocpp/OCPPServiceUtils.ts
src/charging-station/ocpp/index.ts
src/utils/ErrorUtils.ts
tests/charging-station/Helpers.test.ts
tests/charging-station/ocpp/OCPPServiceUtils-pure.test.ts

index fec2fcb68017fda69c0f07613a5385276ac9bbe8..0ad4fcf3476c27794cbca9fea1bbb4d8f5bb235b 100644 (file)
@@ -129,6 +129,7 @@ import {
   getHashId,
   getIdTagsFile,
   getMaxNumberOfEvses,
+  getMessageTypeString,
   getNumberOfReservableConnectors,
   getPhaseRotationValue,
   hasFeatureProfile,
@@ -143,7 +144,6 @@ import {
 } from './Helpers.js'
 import { IdTagsCache } from './IdTagsCache.js'
 import {
-  getMessageTypeString,
   OCPP16IncomingRequestService,
   OCPP16RequestService,
   OCPP16ResponseService,
index 2ae5aedb130e7991a90c0a61cba4f0a2314000e2..e30798d039ab0a53d64b731fabf5a7286c886144 100644 (file)
@@ -1,6 +1,5 @@
 import type { EventEmitter } from 'node:events'
 
-import chalk from 'chalk'
 import {
   addDays,
   addSeconds,
@@ -46,6 +45,7 @@ import {
   ConnectorStatusEnum,
   CurrentType,
   type EvseTemplate,
+  MessageType,
   OCPPVersion,
   RecurrencyKindType,
   type Reservation,
@@ -1026,7 +1026,6 @@ const warnDeprecatedTemplateKey = (
       isNotEmptyString(logMsgToAppend) ? `. ${logMsgToAppend}` : ''
     }`
     logger.warn(`${logPrefix} ${logMsg}`)
-    console.warn(`${chalk.green(logPrefix)} ${chalk.yellow(logMsg)}`)
   }
 }
 
@@ -1511,3 +1510,16 @@ const getRandomSerialNumberSuffix = (params?: {
   }
   return randomSerialNumberSuffix
 }
+
+export const getMessageTypeString = (messageType: MessageType | undefined): string => {
+  switch (messageType) {
+    case MessageType.CALL_ERROR_MESSAGE:
+      return 'error'
+    case MessageType.CALL_MESSAGE:
+      return 'request'
+    case MessageType.CALL_RESULT_MESSAGE:
+      return 'response'
+    default:
+      return 'unknown'
+  }
+}
index b01ac1b69491c5fc4c0dc00fe070c64703779a13..7a48f729f0636c22c17ac59b8df0b09a49f37f2d 100644 (file)
@@ -10,6 +10,7 @@ export {
   checkChargingStationState,
   getConnectorChargingProfiles,
   getIdTagsFile,
+  getMessageTypeString,
   hasFeatureProfile,
   hasPendingReservation,
   hasPendingReservations,
index 8de4b8836a8b88acd9af770aeaee8c572c8bcabe..a81e88570dc25eaabc73650c710c7a7ec94e4892 100644 (file)
@@ -6,6 +6,7 @@ import { join, resolve, sep } from 'node:path'
 
 import type { ChargingStation } from '../../ChargingStation.js'
 
+import { BaseError } from '../../../exception/index.js'
 import {
   type CertificateHashDataChainType,
   type CertificateHashDataType,
@@ -126,7 +127,7 @@ export class OCPP20CertificateManager {
     issuerCertPem?: string
   ): CertificateHashDataType {
     if (!this.validateCertificateFormat(pemData)) {
-      throw new Error('Invalid PEM certificate format')
+      throw new BaseError('Invalid PEM certificate format')
     }
 
     const algorithmName = this.getHashAlgorithmName(hashAlgorithm)
@@ -626,7 +627,7 @@ export class OCPP20CertificateManager {
 
     // Check if resolved path is within the base directory
     if (!fileResolved.startsWith(baseResolved + sep) && fileResolved !== baseResolved) {
-      throw new Error(
+      throw new BaseError(
         `Path traversal attempt detected: certificate path '${certificateFileName}' resolves outside base directory`
       )
     }
index 4a152be5580a13e552f6832139487710a1a7d6ad..0b43690b13d0d2bbfcf3cc31c14ae37a94a2b7bf 100644 (file)
@@ -1,5 +1,6 @@
 import { millisecondsToSeconds } from 'date-fns'
 
+import { BaseError } from '../../../exception/index.js'
 import {
   AttributeEnumType,
   type ComponentType,
@@ -347,7 +348,7 @@ export class OCPP20VariableManager {
   private getStationId (chargingStation: ChargingStation): string {
     const stationId = chargingStation.stationInfo?.hashId
     if (stationId == null) {
-      throw new Error('ChargingStation has no stationInfo.hashId, cannot identify station')
+      throw new BaseError('ChargingStation has no stationInfo.hashId, cannot identify station')
     }
     return stationId
   }
index 01364af193851316e60c4dca871234e5cb23eaa3..3a39a37330491df6fa817d03202f480266656dbc 100644 (file)
@@ -30,12 +30,9 @@ import {
   handleSendMessageError,
   logger,
 } from '../../utils/index.js'
+import { getMessageTypeString } from '../index.js'
 import { OCPPConstants } from './OCPPConstants.js'
-import {
-  ajvErrorsToErrorType,
-  convertDateToISOString,
-  getMessageTypeString,
-} from './OCPPServiceUtils.js'
+import { ajvErrorsToErrorType, convertDateToISOString } from './OCPPServiceUtils.js'
 
 type Ajv = _Ajv.default
 // eslint-disable-next-line @typescript-eslint/no-redeclare
index c90013a68bffa97f51508a3305db037edcabb712..2b7b1304f38667ed39449d60e1366fcf56766093 100644 (file)
@@ -28,7 +28,6 @@ import {
   type MeasurandPerPhaseSampledValueTemplates,
   type MeasurandValues,
   MessageTrigger,
-  MessageType,
   type MeterValue,
   MeterValueContext,
   MeterValueLocation,
@@ -97,19 +96,6 @@ interface SingleValueMeasurandData {
   value: number
 }
 
-export const getMessageTypeString = (messageType: MessageType | undefined): string => {
-  switch (messageType) {
-    case MessageType.CALL_ERROR_MESSAGE:
-      return 'error'
-    case MessageType.CALL_MESSAGE:
-      return 'request'
-    case MessageType.CALL_RESULT_MESSAGE:
-      return 'response'
-    default:
-      return 'unknown'
-  }
-}
-
 export const buildStatusNotificationRequest = (
   chargingStation: ChargingStation,
   commandParams: StatusNotificationRequest
index e8d578b01f0f7194a9f4f73db17c31797776d5e9..bfd92858a07f4435dd47e8a890cd76530e99d003 100644 (file)
@@ -14,7 +14,6 @@ export {
   buildMeterValue,
   buildStatusNotificationRequest,
   buildTransactionEndMeterValue,
-  getMessageTypeString,
   isIdTagAuthorized,
   sendAndSetConnectorStatus,
 } from './OCPPServiceUtils.js'
index 500e4d836225d0207467e73a75a2e8e233ae9fe2..0bea67391652365889392c7dccac994f929a5a02 100644 (file)
@@ -12,7 +12,7 @@ import type {
   RequestCommand,
 } from '../types/index.js'
 
-import { getMessageTypeString } from '../charging-station/ocpp/OCPPServiceUtils.js'
+import { getMessageTypeString } from '../charging-station/index.js'
 import { logger } from './Logger.js'
 import { isNotEmptyString } from './Utils.js'
 
index 6f522fe44fa963fc21c2d7c0f1123d31658fda73..a064f3bb4f0da09176ae3318bd1e68972fe2241a 100644 (file)
@@ -15,6 +15,7 @@ import {
   getChargingStationId,
   getHashId,
   getMaxNumberOfEvses,
+  getMessageTypeString,
   getPhaseRotationValue,
   hasPendingReservation,
   hasPendingReservations,
@@ -31,6 +32,7 @@ import {
   type ChargingStationTemplate,
   type ConnectorStatus,
   ConnectorStatusEnum,
+  MessageType,
   type MeterValue,
   OCPPVersion,
   type Reservation,
@@ -875,4 +877,22 @@ await describe('Helpers', async () => {
       assert.strictEqual(connectorStatus.MeterValues.length, 1)
     })
   })
+
+  await describe('getMessageTypeString', async () => {
+    await it('should return "request" for MessageType.CALL_MESSAGE', () => {
+      assert.strictEqual(getMessageTypeString(MessageType.CALL_MESSAGE), 'request')
+    })
+
+    await it('should return "response" for MessageType.CALL_RESULT_MESSAGE', () => {
+      assert.strictEqual(getMessageTypeString(MessageType.CALL_RESULT_MESSAGE), 'response')
+    })
+
+    await it('should return "error" for MessageType.CALL_ERROR_MESSAGE', () => {
+      assert.strictEqual(getMessageTypeString(MessageType.CALL_ERROR_MESSAGE), 'error')
+    })
+
+    await it('should return "unknown" for undefined', () => {
+      assert.strictEqual(getMessageTypeString(undefined), 'unknown')
+    })
+  })
 })
index f74b6c098c636867c12d6234bc1939e4fdb63bf7..dbb503447411c8ca922676d0ac559bb0d363a77c 100644 (file)
@@ -3,7 +3,6 @@
  * @description Verifies pure utility functions exported from OCPPServiceUtils
  *
  * Covers:
- * - getMessageTypeString — converts MessageType enum to human-readable string
  * - ajvErrorsToErrorType — maps AJV validation errors to OCPP ErrorType
  * - convertDateToISOString — recursively converts Date objects to ISO strings in-place
  * - OCPPServiceUtils.isConnectorIdValid — validates connector ID ranges
@@ -19,15 +18,9 @@ import type { ChargingStation } from '../../../src/charging-station/index.js'
 import {
   ajvErrorsToErrorType,
   convertDateToISOString,
-  getMessageTypeString,
   OCPPServiceUtils,
 } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
-import {
-  ErrorType,
-  IncomingRequestCommand,
-  type JsonType,
-  MessageType,
-} from '../../../src/types/index.js'
+import { ErrorType, IncomingRequestCommand, type JsonType } from '../../../src/types/index.js'
 import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
 
 /**
@@ -57,24 +50,6 @@ await describe('OCPPServiceUtils — pure functions', async () => {
     standardCleanup()
   })
 
-  await describe('getMessageTypeString', async () => {
-    await it('should return "request" for MessageType.CALL_MESSAGE', () => {
-      assert.strictEqual(getMessageTypeString(MessageType.CALL_MESSAGE), 'request')
-    })
-
-    await it('should return "response" for MessageType.CALL_RESULT_MESSAGE', () => {
-      assert.strictEqual(getMessageTypeString(MessageType.CALL_RESULT_MESSAGE), 'response')
-    })
-
-    await it('should return "error" for MessageType.CALL_ERROR_MESSAGE', () => {
-      assert.strictEqual(getMessageTypeString(MessageType.CALL_ERROR_MESSAGE), 'error')
-    })
-
-    await it('should return "unknown" for undefined', () => {
-      assert.strictEqual(getMessageTypeString(undefined), 'unknown')
-    })
-  })
-
   await describe('ajvErrorsToErrorType', async () => {
     await it('should return FormatViolation for null errors', () => {
       assert.strictEqual(ajvErrorsToErrorType(null), ErrorType.FORMAT_VIOLATION)