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