From 2bcd07d72f3b715792897782d43750db25ee0103 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 16 Mar 2026 00:13:20 +0100 Subject: [PATCH] refactor: replace 54 unsafe error casts with instanceof guards All 'error as Error', 'error as OCPPError', and 'error as NodeJS.ErrnoException' casts replaced with proper instanceof type narrowing across 16 files. Uses the pattern already established in the auth strategies module: error instanceof Error ? error.message : String(error) For call sites that pass error objects to functions, wraps non-Error values: error instanceof Error ? error : new Error(String(error)) --- src/charging-station/ChargingStation.ts | 19 +++++++++----- src/charging-station/ChargingStationWorker.ts | 6 ++--- src/charging-station/IdTagsCache.ts | 4 +-- .../ChargingStationWorkerBroadcastChannel.ts | 8 +++--- .../ocpp/1.6/OCPP16IncomingRequestService.ts | 8 +++--- .../ocpp/2.0/OCPP20CertificateManager.ts | 2 +- .../ocpp/OCPPRequestService.ts | 6 ++--- .../ocpp/auth/services/OCPPAuthServiceImpl.ts | 10 +++---- .../ui-server/UIHttpServer.ts | 4 +-- .../ui-server/UIServerUtils.ts | 6 ++++- .../ui-services/AbstractUIService.ts | 26 +++++++++---------- src/performance/storage/JsonFileStorage.ts | 6 ++--- src/performance/storage/MikroOrmStorage.ts | 12 ++++++--- src/performance/storage/MongoDBStorage.ts | 12 ++++++--- src/utils/Configuration.ts | 4 +-- src/utils/FileUtils.ts | 12 ++++++--- 16 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 7e658527..38962392 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -1356,7 +1356,7 @@ export class ChargingStation extends EventEmitter { handleFileException( this.configurationFile, FileType.ChargingStationConfiguration, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix() ) if ( @@ -1628,7 +1628,7 @@ export class ChargingStation extends EventEmitter { handleFileException( this.templateFile, FileType.ChargingStationTemplate, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix() ) } @@ -2211,6 +2211,13 @@ export class ChargingStation extends EventEmitter { let requestCommandName: IncomingRequestCommand | RequestCommand | undefined let errorCallback: ErrorCallback const [, messageId] = request + const ocppError = + error instanceof OCPPError + ? error + : new OCPPError( + ErrorType.INTERNAL_ERROR, + error instanceof Error ? error.message : String(error) + ) switch (messageType) { case MessageType.CALL_ERROR_MESSAGE: case MessageType.CALL_RESULT_MESSAGE: @@ -2218,7 +2225,7 @@ export class ChargingStation extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ;[, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)! // Reject the deferred promise in case of error at response handling (rejecting an already fulfilled promise is a no-op) - errorCallback(error as OCPPError, false) + errorCallback(ocppError, false) } else { // Remove the request from the cache in case of error at response handling this.requests.delete(messageId) @@ -2227,7 +2234,7 @@ export class ChargingStation extends EventEmitter { case MessageType.CALL_MESSAGE: ;[, , commandName] = request as IncomingRequest // Send error - await this.ocppRequestService.sendError(this, messageId, error as OCPPError, commandName) + await this.ocppRequestService.sendError(this, messageId, ocppError, commandName) break } if (!(error instanceof OCPPError)) { @@ -2444,7 +2451,7 @@ export class ChargingStation extends EventEmitter { handleFileException( this.configurationFile, FileType.ChargingStationConfiguration, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix() ) }) @@ -2459,7 +2466,7 @@ export class ChargingStation extends EventEmitter { handleFileException( this.configurationFile, FileType.ChargingStationConfiguration, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix() ) } diff --git a/src/charging-station/ChargingStationWorker.ts b/src/charging-station/ChargingStationWorker.ts index f850a3cd..58f63ff9 100644 --- a/src/charging-station/ChargingStationWorker.ts +++ b/src/charging-station/ChargingStationWorker.ts @@ -64,9 +64,9 @@ if (Configuration.workerPoolInUse()) { parentPort?.postMessage({ data: { event, - message: (error as Error).message, - name: (error as Error).name, - stack: (error as Error).stack, + message: error instanceof Error ? error.message : String(error), + name: error instanceof Error ? error.name : 'UnknownError', + stack: error instanceof Error ? error.stack : undefined, }, event: WorkerMessageEvents.workerElementError, uuid, diff --git a/src/charging-station/IdTagsCache.ts b/src/charging-station/IdTagsCache.ts index 6aed7fb6..dde5d8d1 100644 --- a/src/charging-station/IdTagsCache.ts +++ b/src/charging-station/IdTagsCache.ts @@ -128,7 +128,7 @@ export class IdTagsCache { handleFileException( file, FileType.Authorization, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix(file) ) } @@ -187,7 +187,7 @@ export class IdTagsCache { handleFileException( file, FileType.Authorization, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix(file), { throwError: false, diff --git a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts index b5a728b5..de73e686 100644 --- a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts +++ b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts @@ -2,7 +2,7 @@ import { secondsToMilliseconds } from 'date-fns' import type { ChargingStation } from '../ChargingStation.js' -import { BaseError, type OCPPError } from '../../exception/index.js' +import { BaseError, OCPPError } from '../../exception/index.js' import { AuthorizationStatus, type AuthorizeRequest, @@ -679,9 +679,9 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne ) responsePayload = { command, - errorDetails: (error as OCPPError).details, - errorMessage: (error as OCPPError).message, - errorStack: (error as OCPPError).stack, + errorDetails: error instanceof OCPPError ? error.details : undefined, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, hashId: this.chargingStation.stationInfo?.hashId, requestPayload, status: ResponseStatus.FAILURE, diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 55264ac1..b9c0bdaa 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -645,7 +645,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return handleIncomingRequestError( chargingStation, OCPP16IncomingRequestCommand.CANCEL_RESERVATION, - error as Error, + error instanceof Error ? error : new Error(String(error)), { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED, } @@ -906,7 +906,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return handleIncomingRequestError( chargingStation, OCPP16IncomingRequestCommand.DATA_TRANSFER, - error as Error, + error instanceof Error ? error : new Error(String(error)), { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED } )! } @@ -1150,7 +1150,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return handleIncomingRequestError( chargingStation, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, - error as Error, + error instanceof Error ? error : new Error(String(error)), { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY } )! } @@ -1357,7 +1357,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return handleIncomingRequestError( chargingStation, OCPP16IncomingRequestCommand.RESERVE_NOW, - error as Error, + error instanceof Error ? error : new Error(String(error)), { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED } )! } diff --git a/src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts b/src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts index c44fb2d8..2bdbc697 100644 --- a/src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts +++ b/src/charging-station/ocpp/2.0/OCPP20CertificateManager.ts @@ -421,7 +421,7 @@ export class OCPP20CertificateManager { } } catch (error) { return { - error: `Failed to store certificate: ${(error as Error).message}`, + error: `Failed to store certificate: ${error instanceof Error ? error.message : String(error)}`, success: false, } } diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index 19942fab..b9e09b18 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -116,7 +116,7 @@ export abstract class OCPPRequestService { chargingStation, commandName, MessageType.CALL_ERROR_MESSAGE, - error as Error + error instanceof Error ? error : new Error(String(error)) ) return null } @@ -142,7 +142,7 @@ export abstract class OCPPRequestService { chargingStation, commandName, MessageType.CALL_RESULT_MESSAGE, - error as Error, + error instanceof Error ? error : new Error(String(error)), { throwError: true, } @@ -176,7 +176,7 @@ export abstract class OCPPRequestService { chargingStation, commandName, MessageType.CALL_MESSAGE, - error as Error, + error instanceof Error ? error : new Error(String(error)), { throwError: params.throwError, } diff --git a/src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.ts b/src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.ts index 3a926e34..c88ebd15 100644 --- a/src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.ts +++ b/src/charging-station/ocpp/auth/services/OCPPAuthServiceImpl.ts @@ -144,13 +144,13 @@ export class OCPPAuthServiceImpl implements OCPPAuthService { timestamp: result.timestamp, } } catch (error) { - lastError = error as Error + lastError = error instanceof Error ? error : new Error(String(error)) logger.debug( - `${this.chargingStation.logPrefix()} Strategy '${strategyName}' failed: ${(error as Error).message}` + `${this.chargingStation.logPrefix()} Strategy '${strategyName}' failed: ${error instanceof Error ? error.message : String(error)}` ) // Continue to next strategy unless it's a critical error - if (this.isCriticalError(error as Error)) { + if (this.isCriticalError(error instanceof Error ? error : new Error(String(error)))) { break } } @@ -258,7 +258,7 @@ export class OCPPAuthServiceImpl implements OCPPAuthService { } catch (error) { const duration = Date.now() - startTime logger.error( - `${this.chargingStation.logPrefix()} Direct authentication with ${strategyName} failed (${String(duration)}ms): ${(error as Error).message}` + `${this.chargingStation.logPrefix()} Direct authentication with ${strategyName} failed (${String(duration)}ms): ${error instanceof Error ? error.message : String(error)}` ) throw error } @@ -461,7 +461,7 @@ export class OCPPAuthServiceImpl implements OCPPAuthService { } } catch (error) { logger.debug( - `${this.chargingStation.logPrefix()} Local authorization check failed: ${(error as Error).message}` + `${this.chargingStation.logPrefix()} Local authorization check failed: ${error instanceof Error ? error.message : String(error)}` ) } } diff --git a/src/charging-station/ui-server/UIHttpServer.ts b/src/charging-station/ui-server/UIHttpServer.ts index cf6fee38..10b32a89 100644 --- a/src/charging-station/ui-server/UIHttpServer.ts +++ b/src/charging-station/ui-server/UIHttpServer.ts @@ -202,8 +202,8 @@ export class UIHttpServer extends AbstractUIServer { } catch (error) { this.sendResponse( this.buildProtocolResponse(uuid, { - errorMessage: (error as Error).message, - errorStack: (error as Error).stack, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, status: ResponseStatus.FAILURE, }) ) diff --git a/src/charging-station/ui-server/UIServerUtils.ts b/src/charging-station/ui-server/UIServerUtils.ts index 50ed36f3..94894dde 100644 --- a/src/charging-station/ui-server/UIServerUtils.ts +++ b/src/charging-station/ui-server/UIServerUtils.ts @@ -23,7 +23,11 @@ export const getUsernameAndPasswordFromAuthorizationToken = ( } return [username, password] } catch (error) { - next(new BaseError(`Invalid basic authentication token format: ${(error as Error).message}`)) + next( + new BaseError( + `Invalid basic authentication token format: ${error instanceof Error ? error.message : String(error)}` + ) + ) return undefined } } diff --git a/src/charging-station/ui-server/ui-services/AbstractUIService.ts b/src/charging-station/ui-server/ui-services/AbstractUIService.ts index 98b0e1a7..c7d9453b 100644 --- a/src/charging-station/ui-server/ui-services/AbstractUIService.ts +++ b/src/charging-station/ui-server/ui-services/AbstractUIService.ts @@ -1,6 +1,6 @@ import type { AbstractUIServer } from '../AbstractUIServer.js' -import { BaseError, type OCPPError } from '../../../exception/index.js' +import { BaseError, OCPPError } from '../../../exception/index.js' import { BroadcastChannelProcedureName, type BroadcastChannelRequestPayload, @@ -162,9 +162,9 @@ export abstract class AbstractUIService { logger.error(`${this.logPrefix(moduleName, 'requestHandler')} Handle request error:`, error) responsePayload = { command, - errorDetails: (error as OCPPError).details, - errorMessage: (error as OCPPError).message, - errorStack: (error as OCPPError).stack, + errorDetails: error instanceof OCPPError ? error.details : undefined, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, hashIds: requestPayload?.hashIds, requestPayload, responsePayload, @@ -274,7 +274,7 @@ export abstract class AbstractUIService { succeededStationInfos.push(stationInfo) } } catch (error) { - err = error as Error + err = error instanceof Error ? error : new Error(String(error)) if (stationInfo != null) { failedStationInfos.push(stationInfo) } @@ -326,8 +326,8 @@ export abstract class AbstractUIService { } satisfies ResponsePayload } catch (error) { return { - errorMessage: (error as Error).message, - errorStack: (error as Error).stack, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, status: ResponseStatus.FAILURE, } satisfies ResponsePayload } @@ -341,8 +341,8 @@ export abstract class AbstractUIService { } satisfies ResponsePayload } catch (error) { return { - errorMessage: (error as Error).message, - errorStack: (error as Error).stack, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, status: ResponseStatus.FAILURE, } satisfies ResponsePayload } @@ -354,8 +354,8 @@ export abstract class AbstractUIService { return { status: ResponseStatus.SUCCESS } } catch (error) { return { - errorMessage: (error as Error).message, - errorStack: (error as Error).stack, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, status: ResponseStatus.FAILURE, } satisfies ResponsePayload } @@ -367,8 +367,8 @@ export abstract class AbstractUIService { return { status: ResponseStatus.SUCCESS } } catch (error) { return { - errorMessage: (error as Error).message, - errorStack: (error as Error).stack, + errorMessage: error instanceof Error ? error.message : String(error), + errorStack: error instanceof Error ? error.stack : undefined, status: ResponseStatus.FAILURE, } satisfies ResponsePayload } diff --git a/src/performance/storage/JsonFileStorage.ts b/src/performance/storage/JsonFileStorage.ts index ee145879..c5a9a571 100644 --- a/src/performance/storage/JsonFileStorage.ts +++ b/src/performance/storage/JsonFileStorage.ts @@ -26,7 +26,7 @@ export class JsonFileStorage extends Storage { handleFileException( this.dbName, FileType.PerformanceRecords, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix ) } @@ -42,7 +42,7 @@ export class JsonFileStorage extends Storage { handleFileException( this.dbName, FileType.PerformanceRecords, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix ) } @@ -62,7 +62,7 @@ export class JsonFileStorage extends Storage { handleFileException( this.dbName, FileType.PerformanceRecords, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), this.logPrefix ) }) diff --git a/src/performance/storage/MikroOrmStorage.ts b/src/performance/storage/MikroOrmStorage.ts index 42da83d3..a33b5faa 100644 --- a/src/performance/storage/MikroOrmStorage.ts +++ b/src/performance/storage/MikroOrmStorage.ts @@ -26,7 +26,10 @@ export class MikroOrmStorage extends Storage { delete this.orm } } catch (error) { - this.handleDBStorageError(this.storageType, error as Error) + this.handleDBStorageError( + this.storageType, + error instanceof Error ? error : new Error(String(error)) + ) } } @@ -55,7 +58,10 @@ export class MikroOrmStorage extends Storage { } } } catch (error) { - this.handleDBStorageError(this.storageType, error as Error) + this.handleDBStorageError( + this.storageType, + error instanceof Error ? error : new Error(String(error)) + ) } } @@ -71,7 +77,7 @@ export class MikroOrmStorage extends Storage { } catch (error) { this.handleDBStorageError( this.storageType, - error as Error, + error instanceof Error ? error : new Error(String(error)), Constants.PERFORMANCE_RECORDS_TABLE ) } diff --git a/src/performance/storage/MongoDBStorage.ts b/src/performance/storage/MongoDBStorage.ts index 0dc033d2..96764ab4 100644 --- a/src/performance/storage/MongoDBStorage.ts +++ b/src/performance/storage/MongoDBStorage.ts @@ -26,7 +26,10 @@ export class MongoDBStorage extends Storage { this.opened = false } } catch (error) { - this.handleDBStorageError(StorageType.MONGO_DB, error as Error) + this.handleDBStorageError( + StorageType.MONGO_DB, + error instanceof Error ? error : new Error(String(error)) + ) } } @@ -37,7 +40,10 @@ export class MongoDBStorage extends Storage { this.opened = true } } catch (error) { - this.handleDBStorageError(StorageType.MONGO_DB, error as Error) + this.handleDBStorageError( + StorageType.MONGO_DB, + error instanceof Error ? error : new Error(String(error)) + ) } } @@ -56,7 +62,7 @@ export class MongoDBStorage extends Storage { } catch (error) { this.handleDBStorageError( StorageType.MONGO_DB, - error as Error, + error instanceof Error ? error : new Error(String(error)), Constants.PERFORMANCE_RECORDS_TABLE ) } diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index b4eb5538..5e10c8ef 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -141,7 +141,7 @@ export class Configuration { handleFileException( Configuration.configurationFile, FileType.Configuration, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), logPrefix(), { consoleOut: true } ) @@ -560,7 +560,7 @@ export class Configuration { handleFileException( Configuration.configurationFile, FileType.Configuration, - error as NodeJS.ErrnoException, + error instanceof Error ? error : new Error(String(error)), logPrefix(), { consoleOut: true } ) diff --git a/src/utils/FileUtils.ts b/src/utils/FileUtils.ts index 769f5da7..223b2d27 100644 --- a/src/utils/FileUtils.ts +++ b/src/utils/FileUtils.ts @@ -16,9 +16,15 @@ export const watchJsonFile = ( try { return watch(file, listener) } catch (error) { - handleFileException(file, fileType, error as NodeJS.ErrnoException, logPrefix, { - throwError: false, - }) + handleFileException( + file, + fileType, + error instanceof Error ? error : new Error(String(error)), + logPrefix, + { + throwError: false, + } + ) } } else { logger.info(`${logPrefix} No ${fileType} file to watch given. Not monitoring its changes`) -- 2.43.0