refactor: order configuration class methods
[e-mobility-charging-stations-simulator.git] / src / utils / Configuration.ts
CommitLineData
d972af76
JB
1import { type FSWatcher, readFileSync, watch } from 'node:fs';
2import { dirname, join, resolve } from 'node:path';
130783a7 3import { fileURLToPath } from 'node:url';
8114d10e
JB
4
5import chalk from 'chalk';
088ee3c1 6import merge from 'just-merge';
8114d10e 7
878e026c 8import { Constants } from './Constants';
9bf0ef23 9import { hasOwnProp, isCFEnvironment, isNotEmptyString, isUndefined } from './Utils';
83e00df1 10import {
268a74bb 11 ApplicationProtocol,
83e00df1 12 type ConfigurationData,
5d049829 13 ConfigurationSection,
268a74bb 14 FileType,
3d48c1c1 15 type LogConfiguration,
83e00df1
JB
16 type StationTemplateUrl,
17 type StorageConfiguration,
268a74bb 18 StorageType,
e7aeea18 19 SupervisionUrlDistribution,
83e00df1
JB
20 type UIServerConfiguration,
21 type WorkerConfiguration,
268a74bb
JB
22} from '../types';
23import { WorkerConstants, WorkerProcessType } from '../worker';
7dde0b73 24
268a74bb 25export class Configuration {
d972af76
JB
26 private static configurationFile = join(
27 dirname(fileURLToPath(import.meta.url)),
e7aeea18 28 'assets',
5edd8ba0 29 'config.json',
e7aeea18 30 );
10068088 31
d972af76 32 private static configurationFileWatcher: FSWatcher | undefined;
f74e97ac 33 private static configurationData: ConfigurationData | null = null;
974efe6c
JB
34 private static configurationSectionCache = new Map<
35 ConfigurationSection,
36 LogConfiguration | StorageConfiguration | WorkerConfiguration | UIServerConfiguration
5d049829
JB
37 >([
38 [ConfigurationSection.log, Configuration.buildLogSection()],
39 [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()],
40 [ConfigurationSection.worker, Configuration.buildWorkerSection()],
41 [ConfigurationSection.uiServer, Configuration.buildUIServerSection()],
42 ]);
974efe6c 43
e57acf6a
JB
44 private static configurationChangeCallback: () => Promise<void>;
45
d5bd1c00
JB
46 private constructor() {
47 // This is intentional
48 }
49
aa7d6d95 50 public static setConfigurationChangeCallback(cb: () => Promise<void>): void {
e57acf6a
JB
51 Configuration.configurationChangeCallback = cb;
52 }
7dde0b73 53
5d049829
JB
54 public static getConfigurationSection<T>(sectionName: ConfigurationSection): T {
55 return Configuration.configurationSectionCache.get(sectionName) as T;
56 }
57
58 public static getAutoReconnectMaxRetries(): number | undefined {
59 Configuration.warnDeprecatedConfigurationKey(
60 'autoReconnectTimeout',
61 undefined,
62 "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead",
63 );
64 Configuration.warnDeprecatedConfigurationKey(
65 'connectionTimeout',
66 undefined,
67 "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead",
68 );
69 Configuration.warnDeprecatedConfigurationKey(
70 'autoReconnectMaxRetries',
71 undefined,
72 'Use it in charging station template instead',
73 );
74 if (hasOwnProp(Configuration.getConfigurationData(), 'autoReconnectMaxRetries')) {
75 return Configuration.getConfigurationData()?.autoReconnectMaxRetries;
76 }
77 }
78
79 public static getStationTemplateUrls(): StationTemplateUrl[] | undefined {
80 Configuration.warnDeprecatedConfigurationKey(
81 'stationTemplateURLs',
82 undefined,
83 "Use 'stationTemplateUrls' instead",
84 );
85 // eslint-disable-next-line @typescript-eslint/dot-notation
86 !isUndefined(Configuration.getConfigurationData()!['stationTemplateURLs']) &&
87 (Configuration.getConfigurationData()!.stationTemplateUrls =
88 Configuration.getConfigurationData()![
89 // eslint-disable-next-line @typescript-eslint/dot-notation
90 'stationTemplateURLs'
91 ] as StationTemplateUrl[]);
92 Configuration.getConfigurationData()!.stationTemplateUrls.forEach(
93 (stationTemplateUrl: StationTemplateUrl) => {
94 // eslint-disable-next-line @typescript-eslint/dot-notation
95 if (!isUndefined(stationTemplateUrl['numberOfStation'])) {
96 console.error(
97 `${chalk.green(Configuration.logPrefix())} ${chalk.red(
98 `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`,
99 )}`,
100 );
101 }
102 },
103 );
104 return Configuration.getConfigurationData()?.stationTemplateUrls;
105 }
106
5d049829
JB
107 public static getSupervisionUrls(): string | string[] | undefined {
108 Configuration.warnDeprecatedConfigurationKey(
109 'supervisionURLs',
110 undefined,
111 "Use 'supervisionUrls' instead",
112 );
113 // eslint-disable-next-line @typescript-eslint/dot-notation
114 if (!isUndefined(Configuration.getConfigurationData()!['supervisionURLs'])) {
115 Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![
116 // eslint-disable-next-line @typescript-eslint/dot-notation
117 'supervisionURLs'
118 ] as string | string[];
119 }
120 return Configuration.getConfigurationData()?.supervisionUrls;
121 }
122
123 public static getSupervisionUrlDistribution(): SupervisionUrlDistribution | undefined {
124 Configuration.warnDeprecatedConfigurationKey(
125 'distributeStationToTenantEqually',
126 undefined,
127 "Use 'supervisionUrlDistribution' instead",
128 );
129 Configuration.warnDeprecatedConfigurationKey(
130 'distributeStationsToTenantsEqually',
131 undefined,
132 "Use 'supervisionUrlDistribution' instead",
133 );
134 return hasOwnProp(Configuration.getConfigurationData(), 'supervisionUrlDistribution')
135 ? Configuration.getConfigurationData()?.supervisionUrlDistribution
136 : SupervisionUrlDistribution.ROUND_ROBIN;
137 }
138
c831d2bc
JB
139 public static workerPoolInUse(): boolean {
140 return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes(
141 Configuration.buildWorkerSection().processType!,
142 );
143 }
144
145 public static workerDynamicPoolInUse(): boolean {
146 return Configuration.buildWorkerSection().processType === WorkerProcessType.dynamicPool;
147 }
148
5d049829 149 private static buildUIServerSection(): UIServerConfiguration {
f74e97ac 150 if (hasOwnProp(Configuration.getConfigurationData(), 'uiWebSocketServer')) {
66271092 151 console.error(
c5e52a07 152 `${chalk.green(Configuration.logPrefix())} ${chalk.red(
974efe6c 153 `Deprecated configuration section 'uiWebSocketServer' usage. Use '${ConfigurationSection.uiServer}' instead`,
5edd8ba0 154 )}`,
66271092
JB
155 );
156 }
675fa8e3 157 let uiServerConfiguration: UIServerConfiguration = {
b803eefa 158 enabled: false,
1f7fa4de 159 type: ApplicationProtocol.WS,
c127bd64 160 options: {
adbddcb4
JB
161 host: Constants.DEFAULT_UI_SERVER_HOST,
162 port: Constants.DEFAULT_UI_SERVER_PORT,
c127bd64 163 },
6a49ad23 164 };
f74e97ac 165 if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.uiServer)) {
598c886d
JB
166 uiServerConfiguration = merge<UIServerConfiguration>(
167 uiServerConfiguration,
f74e97ac 168 Configuration.getConfigurationData()!.uiServer!,
598c886d 169 );
6a49ad23 170 }
9bf0ef23 171 if (isCFEnvironment() === true) {
72092cfc 172 delete uiServerConfiguration.options?.host;
e1d9a0f4 173 uiServerConfiguration.options!.port = parseInt(process.env.PORT!);
b803eefa 174 }
5d049829 175 return uiServerConfiguration;
6a49ad23
JB
176 }
177
5d049829 178 private static buildPerformanceStorageSection(): StorageConfiguration {
974efe6c
JB
179 Configuration.warnDeprecatedConfigurationKey(
180 'URI',
181 ConfigurationSection.performanceStorage,
182 "Use 'uri' instead",
183 );
6a49ad23
JB
184 let storageConfiguration: StorageConfiguration = {
185 enabled: false,
186 type: StorageType.JSON_FILE,
e7aeea18 187 uri: this.getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
6a49ad23 188 };
f74e97ac 189 if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.performanceStorage)) {
e7aeea18 190 storageConfiguration = {
1ba1e8fb 191 ...storageConfiguration,
f74e97ac
JB
192 ...Configuration.getConfigurationData()?.performanceStorage,
193 ...(Configuration.getConfigurationData()?.performanceStorage?.type ===
194 StorageType.JSON_FILE &&
195 Configuration.getConfigurationData()?.performanceStorage?.uri && {
e8044a69 196 uri: Configuration.buildPerformanceUriFilePath(
f74e97ac 197 new URL(Configuration.getConfigurationData()!.performanceStorage!.uri!).pathname,
e8044a69 198 ),
f682b2dc 199 }),
72f041bd 200 };
72f041bd 201 }
5d049829 202 return storageConfiguration;
7dde0b73
JB
203 }
204
5d049829 205 private static buildLogSection(): LogConfiguration {
3d48c1c1
JB
206 Configuration.warnDeprecatedConfigurationKey(
207 'logEnabled',
208 undefined,
974efe6c 209 `Use '${ConfigurationSection.log}' section to define the logging enablement instead`,
3d48c1c1
JB
210 );
211 Configuration.warnDeprecatedConfigurationKey(
212 'logFile',
213 undefined,
974efe6c 214 `Use '${ConfigurationSection.log}' section to define the log file instead`,
3d48c1c1
JB
215 );
216 Configuration.warnDeprecatedConfigurationKey(
217 'logErrorFile',
218 undefined,
974efe6c 219 `Use '${ConfigurationSection.log}' section to define the log error file instead`,
3d48c1c1
JB
220 );
221 Configuration.warnDeprecatedConfigurationKey(
222 'logConsole',
223 undefined,
974efe6c 224 `Use '${ConfigurationSection.log}' section to define the console logging enablement instead`,
3d48c1c1
JB
225 );
226 Configuration.warnDeprecatedConfigurationKey(
227 'logStatisticsInterval',
228 undefined,
974efe6c 229 `Use '${ConfigurationSection.log}' section to define the log statistics interval instead`,
3d48c1c1
JB
230 );
231 Configuration.warnDeprecatedConfigurationKey(
232 'logLevel',
233 undefined,
974efe6c 234 `Use '${ConfigurationSection.log}' section to define the log level instead`,
3d48c1c1
JB
235 );
236 Configuration.warnDeprecatedConfigurationKey(
237 'logFormat',
238 undefined,
974efe6c 239 `Use '${ConfigurationSection.log}' section to define the log format instead`,
3d48c1c1
JB
240 );
241 Configuration.warnDeprecatedConfigurationKey(
242 'logRotate',
243 undefined,
974efe6c 244 `Use '${ConfigurationSection.log}' section to define the log rotation enablement instead`,
3d48c1c1
JB
245 );
246 Configuration.warnDeprecatedConfigurationKey(
247 'logMaxFiles',
248 undefined,
974efe6c 249 `Use '${ConfigurationSection.log}' section to define the log maximum files instead`,
3d48c1c1
JB
250 );
251 Configuration.warnDeprecatedConfigurationKey(
252 'logMaxSize',
253 undefined,
974efe6c 254 `Use '${ConfigurationSection.log}' section to define the log maximum size instead`,
3d48c1c1
JB
255 );
256 const defaultLogConfiguration: LogConfiguration = {
257 enabled: true,
258 file: 'logs/combined.log',
259 errorFile: 'logs/error.log',
260 statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL,
261 level: 'info',
262 format: 'simple',
263 rotate: true,
264 };
265 const deprecatedLogConfiguration: LogConfiguration = {
f74e97ac
JB
266 ...(hasOwnProp(Configuration.getConfigurationData(), 'logEnabled') && {
267 enabled: Configuration.getConfigurationData()?.logEnabled,
3d48c1c1 268 }),
f74e97ac
JB
269 ...(hasOwnProp(Configuration.getConfigurationData(), 'logFile') && {
270 file: Configuration.getConfigurationData()?.logFile,
3d48c1c1 271 }),
f74e97ac
JB
272 ...(hasOwnProp(Configuration.getConfigurationData(), 'logErrorFile') && {
273 errorFile: Configuration.getConfigurationData()?.logErrorFile,
3d48c1c1 274 }),
f74e97ac
JB
275 ...(hasOwnProp(Configuration.getConfigurationData(), 'logStatisticsInterval') && {
276 statisticsInterval: Configuration.getConfigurationData()?.logStatisticsInterval,
3d48c1c1 277 }),
f74e97ac
JB
278 ...(hasOwnProp(Configuration.getConfigurationData(), 'logLevel') && {
279 level: Configuration.getConfigurationData()?.logLevel,
3d48c1c1 280 }),
f74e97ac
JB
281 ...(hasOwnProp(Configuration.getConfigurationData(), 'logConsole') && {
282 console: Configuration.getConfigurationData()?.logConsole,
3d48c1c1 283 }),
f74e97ac
JB
284 ...(hasOwnProp(Configuration.getConfigurationData(), 'logFormat') && {
285 format: Configuration.getConfigurationData()?.logFormat,
3d48c1c1 286 }),
f74e97ac
JB
287 ...(hasOwnProp(Configuration.getConfigurationData(), 'logRotate') && {
288 rotate: Configuration.getConfigurationData()?.logRotate,
3d48c1c1 289 }),
f74e97ac
JB
290 ...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxFiles') && {
291 maxFiles: Configuration.getConfigurationData()?.logMaxFiles,
3d48c1c1 292 }),
f74e97ac
JB
293 ...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxSize') && {
294 maxSize: Configuration.getConfigurationData()?.logMaxSize,
3d48c1c1
JB
295 }),
296 };
297 const logConfiguration: LogConfiguration = {
298 ...defaultLogConfiguration,
299 ...deprecatedLogConfiguration,
f74e97ac
JB
300 ...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.log) &&
301 Configuration.getConfigurationData()?.log),
3d48c1c1 302 };
5d049829 303 return logConfiguration;
3d48c1c1
JB
304 }
305
5d049829 306 private static buildWorkerSection(): WorkerConfiguration {
e7aeea18 307 Configuration.warnDeprecatedConfigurationKey(
e80bc579 308 'useWorkerPool',
1895299d 309 undefined,
974efe6c 310 `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`,
cf2a5d9b
JB
311 );
312 Configuration.warnDeprecatedConfigurationKey(
313 'workerProcess',
1895299d 314 undefined,
974efe6c 315 `Use '${ConfigurationSection.worker}' section to define the type of worker process model instead`,
cf2a5d9b
JB
316 );
317 Configuration.warnDeprecatedConfigurationKey(
318 'workerStartDelay',
1895299d 319 undefined,
974efe6c 320 `Use '${ConfigurationSection.worker}' section to define the worker start delay instead`,
cf2a5d9b
JB
321 );
322 Configuration.warnDeprecatedConfigurationKey(
323 'chargingStationsPerWorker',
1895299d 324 undefined,
974efe6c 325 `Use '${ConfigurationSection.worker}' section to define the number of element(s) per worker instead`,
cf2a5d9b
JB
326 );
327 Configuration.warnDeprecatedConfigurationKey(
328 'elementStartDelay',
1895299d 329 undefined,
974efe6c 330 `Use '${ConfigurationSection.worker}' section to define the worker's element start delay instead`,
cf2a5d9b
JB
331 );
332 Configuration.warnDeprecatedConfigurationKey(
333 'workerPoolMinSize',
1895299d 334 undefined,
974efe6c 335 `Use '${ConfigurationSection.worker}' section to define the worker pool minimum size instead`,
e7aeea18 336 );
e7aeea18
JB
337 Configuration.warnDeprecatedConfigurationKey(
338 'workerPoolSize;',
1895299d 339 undefined,
974efe6c 340 `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
e7aeea18 341 );
cf2a5d9b
JB
342 Configuration.warnDeprecatedConfigurationKey(
343 'workerPoolMaxSize;',
1895299d 344 undefined,
974efe6c 345 `Use '${ConfigurationSection.worker}' section to define the worker pool maximum size instead`,
cf2a5d9b
JB
346 );
347 Configuration.warnDeprecatedConfigurationKey(
348 'workerPoolStrategy;',
1895299d 349 undefined,
974efe6c 350 `Use '${ConfigurationSection.worker}' section to define the worker pool strategy instead`,
cf2a5d9b 351 );
3d48c1c1
JB
352 const defaultWorkerConfiguration: WorkerConfiguration = {
353 processType: WorkerProcessType.workerSet,
354 startDelay: WorkerConstants.DEFAULT_WORKER_START_DELAY,
8603c1ca 355 elementsPerWorker: 'auto',
3d48c1c1
JB
356 elementStartDelay: WorkerConstants.DEFAULT_ELEMENT_START_DELAY,
357 poolMinSize: WorkerConstants.DEFAULT_POOL_MIN_SIZE,
358 poolMaxSize: WorkerConstants.DEFAULT_POOL_MAX_SIZE,
3d48c1c1 359 };
f74e97ac
JB
360 hasOwnProp(Configuration.getConfigurationData(), 'workerPoolStrategy') &&
361 delete Configuration.getConfigurationData()?.workerPoolStrategy;
3d48c1c1 362 const deprecatedWorkerConfiguration: WorkerConfiguration = {
f74e97ac
JB
363 ...(hasOwnProp(Configuration.getConfigurationData(), 'workerProcess') && {
364 processType: Configuration.getConfigurationData()?.workerProcess,
3d48c1c1 365 }),
f74e97ac
JB
366 ...(hasOwnProp(Configuration.getConfigurationData(), 'workerStartDelay') && {
367 startDelay: Configuration.getConfigurationData()?.workerStartDelay,
3d48c1c1 368 }),
f74e97ac
JB
369 ...(hasOwnProp(Configuration.getConfigurationData(), 'chargingStationsPerWorker') && {
370 elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker,
3d48c1c1 371 }),
f74e97ac
JB
372 ...(hasOwnProp(Configuration.getConfigurationData(), 'elementStartDelay') && {
373 elementStartDelay: Configuration.getConfigurationData()?.elementStartDelay,
3d48c1c1 374 }),
f74e97ac
JB
375 ...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMinSize') && {
376 poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize,
3d48c1c1 377 }),
f74e97ac
JB
378 ...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMaxSize') && {
379 poolMaxSize: Configuration.getConfigurationData()?.workerPoolMaxSize,
3d48c1c1 380 }),
3d48c1c1 381 };
eda9c451
JB
382 Configuration.warnDeprecatedConfigurationKey(
383 'poolStrategy',
974efe6c 384 ConfigurationSection.worker,
eda9c451
JB
385 'Not publicly exposed to end users',
386 );
3d48c1c1
JB
387 const workerConfiguration: WorkerConfiguration = {
388 ...defaultWorkerConfiguration,
389 ...deprecatedWorkerConfiguration,
f74e97ac
JB
390 ...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.worker) &&
391 Configuration.getConfigurationData()?.worker),
cf2a5d9b 392 };
b5b2c3e8
JB
393 if (!Object.values(WorkerProcessType).includes(workerConfiguration.processType!)) {
394 throw new SyntaxError(
395 `Invalid worker process type '${workerConfiguration.processType}' defined in configuration`,
396 );
397 }
5d049829 398 return workerConfiguration;
7dde0b73 399 }
eb3937cb 400
8b7072dc 401 private static logPrefix = (): string => {
14ecae6a 402 return `${new Date().toLocaleString()} Simulator configuration |`;
8b7072dc 403 };
23132a44 404
e7aeea18
JB
405 private static warnDeprecatedConfigurationKey(
406 key: string,
407 sectionName?: string,
5edd8ba0 408 logMsgToAppend = '',
e7aeea18 409 ) {
e7aeea18
JB
410 if (
411 sectionName &&
f74e97ac
JB
412 !isUndefined(Configuration.getConfigurationData()![sectionName]) &&
413 !isUndefined(
414 (Configuration.getConfigurationData()![sectionName] as Record<string, unknown>)[key],
415 )
e7aeea18
JB
416 ) {
417 console.error(
c5e52a07
JB
418 `${chalk.green(Configuration.logPrefix())} ${chalk.red(
419 `Deprecated configuration key '${key}' usage in section '${sectionName}'${
420 logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
5edd8ba0
JB
421 }`,
422 )}`,
e7aeea18 423 );
f74e97ac 424 } else if (!isUndefined(Configuration.getConfigurationData()![key])) {
e7aeea18 425 console.error(
c5e52a07
JB
426 `${chalk.green(Configuration.logPrefix())} ${chalk.red(
427 `Deprecated configuration key '${key}' usage${
428 logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
5edd8ba0
JB
429 }`,
430 )}`,
e7aeea18 431 );
eb3937cb
JB
432 }
433 }
434
f74e97ac
JB
435 private static getConfigurationData(): ConfigurationData | null {
436 if (!Configuration.configurationData) {
23132a44 437 try {
f74e97ac 438 Configuration.configurationData = JSON.parse(
5edd8ba0 439 readFileSync(Configuration.configurationFile, 'utf8'),
e7aeea18 440 ) as ConfigurationData;
23132a44 441 } catch (error) {
69074173 442 Configuration.handleFileException(
a95873d8 443 Configuration.configurationFile,
7164966d
JB
444 FileType.Configuration,
445 error as NodeJS.ErrnoException,
5edd8ba0 446 Configuration.logPrefix(),
e7aeea18 447 );
23132a44 448 }
ded13d97
JB
449 if (!Configuration.configurationFileWatcher) {
450 Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher();
451 }
eb3937cb 452 }
f74e97ac 453 return Configuration.configurationData;
eb3937cb 454 }
963ee397 455
d972af76 456 private static getConfigurationFileWatcher(): FSWatcher | undefined {
23132a44 457 try {
d972af76 458 return watch(Configuration.configurationFile, (event, filename): void => {
e1d9a0f4 459 if (filename!.trim()!.length > 0 && event === 'change') {
3ec10737 460 // Nullify to force configuration file reading
f74e97ac 461 Configuration.configurationData = null;
974efe6c 462 Configuration.configurationSectionCache.clear();
9bf0ef23 463 if (!isUndefined(Configuration.configurationChangeCallback)) {
72092cfc 464 Configuration.configurationChangeCallback().catch((error) => {
dcaf96dc
JB
465 throw typeof error === 'string' ? new Error(error) : error;
466 });
3ec10737 467 }
23132a44
JB
468 }
469 });
470 } catch (error) {
69074173 471 Configuration.handleFileException(
a95873d8 472 Configuration.configurationFile,
7164966d
JB
473 FileType.Configuration,
474 error as NodeJS.ErrnoException,
5edd8ba0 475 Configuration.logPrefix(),
e7aeea18 476 );
23132a44 477 }
ded13d97
JB
478 }
479
69074173
JB
480 private static handleFileException(
481 file: string,
482 fileType: FileType,
483 error: NodeJS.ErrnoException,
5edd8ba0 484 logPrefix: string,
69074173 485 ): void {
9bf0ef23 486 const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : '';
69074173
JB
487 let logMsg: string;
488 switch (error.code) {
489 case 'ENOENT':
490 logMsg = `${fileType} file ${file} not found:`;
491 break;
492 case 'EEXIST':
493 logMsg = `${fileType} file ${file} already exists:`;
494 break;
495 case 'EACCES':
496 logMsg = `${fileType} file ${file} access denied:`;
497 break;
7b5dbe91
JB
498 case 'EPERM':
499 logMsg = `${fileType} file ${file} permission denied:`;
500 break;
69074173
JB
501 default:
502 logMsg = `${fileType} file ${file} error:`;
503 }
7b5dbe91
JB
504 console.error(`${chalk.green(prefix)}${chalk.red(`${logMsg} `)}`, error);
505 throw error;
69074173
JB
506 }
507
1f5df42a 508 private static getDefaultPerformanceStorageUri(storageType: StorageType) {
d5603918
JB
509 switch (storageType) {
510 case StorageType.JSON_FILE:
e8044a69 511 return Configuration.buildPerformanceUriFilePath(
5edd8ba0 512 `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_FILENAME}`,
e8044a69 513 );
d5603918 514 case StorageType.SQLITE:
e8044a69 515 return Configuration.buildPerformanceUriFilePath(
5edd8ba0 516 `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`,
e8044a69 517 );
d5603918
JB
518 default:
519 throw new Error(`Performance storage URI is mandatory with storage type '${storageType}'`);
520 }
521 }
e8044a69
JB
522
523 private static buildPerformanceUriFilePath(file: string) {
d972af76 524 return `file://${join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), file)}`;
e8044a69 525 }
7dde0b73 526}