@ti-engine/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/utils/cache.js ADDED
@@ -0,0 +1,507 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: © 2021 Boris Kostadinov <kostadinov.boris@gmail.com>
3
+ * SPDX-License-Identifier: ICU
4
+ */
5
+
6
+ const ConnectionObserver = require( "#connection-observer" );
7
+ const _ = require( "lodash" );
8
+ const config = require( "#config" );
9
+ const tools = require( "#tools" );
10
+ const redis = require( "#redis-integration" );
11
+ const exceptions = require( "#exceptions" );
12
+
13
+ /**
14
+ * Used to create and/or return a Common Memory Cache singleton instance.
15
+ *
16
+ * @class CommonMemoryCache
17
+ * @extends ConnectionObserver
18
+ * @singleton
19
+ * @public
20
+ */
21
+ class CommonMemoryCache extends ConnectionObserver {
22
+
23
+ static #instance = null;
24
+ #redisClient = null;
25
+ #isOperational = false;
26
+
27
+ /**
28
+ * @constructor
29
+ * @return {CommonMemoryCache}
30
+ */
31
+ constructor() {
32
+ super();
33
+
34
+ if ( !CommonMemoryCache.#instance ) {
35
+ let host = config.getSetting( config.setting.MEMORY_CACHE_REDIS_HOST );
36
+ let port = config.getSetting( config.setting.MEMORY_CACHE_REDIS_PORT );
37
+ let db = config.getSetting( config.setting.MEMORY_CACHE_REDIS_DB );
38
+ let authKey = config.getSetting( config.setting.MEMORY_CACHE_AUTH_KEY );
39
+ this.#redisClient = redis.createRedisClient( "system", host, port, authKey, db );
40
+ this.#redisClient.addConnectionObserver( this );
41
+ CommonMemoryCache.#instance = this;
42
+ }
43
+ return CommonMemoryCache.#instance;
44
+ }
45
+
46
+ /* Public interface */
47
+
48
+ /**
49
+ * Property returning the operational state of the cache.
50
+ *
51
+ * @property
52
+ * @returns {boolean}
53
+ * @public
54
+ */
55
+ get isOperational() { return this.#isOperational; }
56
+
57
+ /**
58
+ * Needs to be invoked by the connection handler when the connection is disrupted.
59
+ *
60
+ * @method
61
+ * @param {string} identifier The identifier of the observed connection.
62
+ * @override
63
+ * @public
64
+ */
65
+ onConnectionDisrupted( identifier ) {
66
+ this.#isOperational = false;
67
+ }
68
+
69
+ /**
70
+ * Needs to be invoked by the connection handler when the connection is recovered.
71
+ *
72
+ * @method
73
+ * @param {string} identifier The identifier of the observed connection.
74
+ * @override
75
+ * @public
76
+ */
77
+ onConnectionRecovered( identifier ) {
78
+ this.#isOperational = true;
79
+ }
80
+
81
+ /**
82
+ * Used to register a new {@link ConnectionObserver} for events related to the underlying Redis connection state.
83
+ *
84
+ * @method
85
+ * @param {ConnectionObserver} connectionObserver The {@link ConnectionObserver} that will be notified of any changes.
86
+ * @public
87
+ */
88
+ addConnectionObserver( connectionObserver ) {
89
+ this.#redisClient.addConnectionObserver( connectionObserver );
90
+ }
91
+
92
+ /**
93
+ * Used to search for keys by given pattern.
94
+ *
95
+ * @method
96
+ * @param {string} pattern
97
+ * @returns {Promise<Array>}
98
+ * @public
99
+ */
100
+ matchKeys( pattern ) {
101
+ return new Promise( ( resolve, reject ) => {
102
+ if ( this.#isOperational === true ) {
103
+ let commandKeys = [ redis.cacheCommands.KEYS, pattern ];
104
+ this.#redisClient.executeCommands( [ commandKeys ] ).then( ( results ) => {
105
+ results = results[ 0 ];
106
+ resolve( ( results && results.length > 1 ) ? results[ 1 ] : [] );
107
+ } ).catch( ( error ) => {
108
+ reject( error );
109
+ } );
110
+ } else {
111
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
112
+ }
113
+ } );
114
+ }
115
+
116
+ /**
117
+ * Used to set a specific string value.
118
+ *
119
+ * @method
120
+ * @param {string} key
121
+ * @param {string} value
122
+ * @param {number} [expiration] Expiration value is in seconds.
123
+ * @return {Promise<string>}
124
+ * @public
125
+ */
126
+ setValue( key, value, expiration ) {
127
+ return new Promise( ( resolve, reject ) => {
128
+ if ( this.#isOperational === true ) {
129
+ if ( value ) {
130
+ let commandSetValue = [ redis.cacheCommands.SET_VALUE, key, tools.stringifyJSON( value ) ];
131
+ if ( expiration ) {
132
+ commandSetValue.push( "EX" );
133
+ commandSetValue.push( expiration );
134
+ }
135
+ this.#redisClient.executeCommands( [ commandSetValue ] ).then( () => {
136
+ resolve( value );
137
+ } ).catch( ( error ) => {
138
+ reject( error );
139
+ } );
140
+ } else {
141
+ resolve( value );
142
+ }
143
+ } else {
144
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
145
+ }
146
+ } );
147
+ }
148
+
149
+ /**
150
+ * Used to set multiple string values.
151
+ *
152
+ * @method
153
+ * @param {Object} keyValues
154
+ * @param {string} [prefix]
155
+ * @param {number} [expiration]
156
+ * @return {Promise}
157
+ * @public
158
+ */
159
+ setValues( keyValues, prefix, expiration ) {
160
+ return new Promise( ( resolve, reject ) => {
161
+ if ( this.#isOperational === true ) {
162
+ if ( keyValues ) {
163
+ let commands = [];
164
+ _.forEach( keyValues, ( value, key ) => {
165
+ let commandSetValue = [ redis.cacheCommands.SET_VALUE, ( ( prefix ) ? prefix : "" ) + key, tools.stringifyJSON( value ) ];
166
+ if ( expiration ) {
167
+ commandSetValue.push( "EX" );
168
+ commandSetValue.push( expiration );
169
+ }
170
+ commands.push( commandSetValue );
171
+ } );
172
+
173
+ this.#redisClient.executeCommands( commands ).then( () => {
174
+ resolve( keyValues );
175
+ } ).catch( ( error ) => {
176
+ reject( error );
177
+ } );
178
+ } else {
179
+ resolve( keyValues );
180
+ }
181
+ } else {
182
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
183
+ }
184
+ } );
185
+ }
186
+
187
+ /**
188
+ * Used to get a string value.
189
+ *
190
+ * @method
191
+ * @param {string} key
192
+ * @return {Promise}
193
+ * @public
194
+ */
195
+ getValue( key ) {
196
+ return new Promise( ( resolve, reject ) => {
197
+ if ( this.#isOperational === true ) {
198
+ let commandGetValue = [ redis.cacheCommands.GET_VALUE, key ];
199
+ this.#redisClient.executeCommands( [ commandGetValue ] ).then( ( results ) => {
200
+ results = results[ 0 ];
201
+ resolve( ( results && results.length > 1 && _.isString( results[ 1 ] ) ) ? tools.parseJSON( results[ 1 ] ) : undefined );
202
+ } ).catch( ( error ) => {
203
+ reject( error );
204
+ } );
205
+ } else {
206
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
207
+ }
208
+ } );
209
+ }
210
+
211
+ /**
212
+ * Used to get multiple string values.
213
+ *
214
+ * @method
215
+ * @param {string[]} keys
216
+ * @param {string} [prefix]
217
+ * @return {Promise}
218
+ * @public
219
+ */
220
+ getValues( keys, prefix ) {
221
+ return new Promise( ( resolve, reject ) => {
222
+ if ( this.#isOperational === true ) {
223
+ let commands = [];
224
+ _.forEach( keys, ( key ) => {
225
+ commands.push( [ redis.cacheCommands.GET_VALUE, ( ( prefix ) ? prefix : "" ) + key ] );
226
+ } );
227
+ this.#redisClient.executeCommands( commands ).then( ( rawResults ) => {
228
+ let results = {};
229
+ _.forEach( rawResults, ( result, idx ) => {
230
+ results[ keys[ idx ] ] = ( results && results.length > 1 && _.isString( results[ 1 ] ) ) ? tools.parseJSON( results[ 1 ] ) : null;
231
+ } );
232
+ resolve( results );
233
+ } ).catch( ( error ) => {
234
+ reject( error );
235
+ } );
236
+ } else {
237
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
238
+ }
239
+ } );
240
+ }
241
+
242
+ /**
243
+ * Used to delete a value / item.
244
+ *
245
+ * @method
246
+ * @param {string} key
247
+ * @returns {Promise<boolean>}
248
+ * @public
249
+ */
250
+ deleteValue( key ) {
251
+ return new Promise( ( resolve, reject ) => {
252
+ if ( this.#isOperational === true ) {
253
+ let commandDeleteValue = [ redis.cacheCommands.DELETE_VALUE, key ];
254
+ this.#redisClient.executeCommands( [ commandDeleteValue ] ).then( ( results ) => {
255
+ results = results[ 0 ];
256
+ resolve( ( results && results.length > 1 ) ? results[ 1 ] : undefined );
257
+ } ).catch( ( error ) => {
258
+ reject( error );
259
+ } );
260
+ } else {
261
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
262
+ }
263
+ } );
264
+ }
265
+
266
+ /**
267
+ * Used to add the specified values to a list.
268
+ *
269
+ * @method
270
+ * @param {string} listName
271
+ * @param {Object[]} values
272
+ * @returns {Promise<number>}
273
+ * @public
274
+ */
275
+ listPushValue( listName, values ) {
276
+ return new Promise( ( resolve, reject ) => {
277
+ if ( this.#isOperational === true ) {
278
+ let commandPushValues = [ redis.cacheCommands.LIST_PUSH, listName ];
279
+ _.forEach( values, ( value ) => {
280
+ if ( value ) {
281
+ commandPushValues.push( tools.stringifyJSON( value ) );
282
+ }
283
+ } );
284
+ this.#redisClient.executeCommands( [ commandPushValues ] ).then( ( results ) => {
285
+ results = results[ 0 ];
286
+ resolve( ( results && results.length > 1 ) ? results[ 1 ] : undefined );
287
+ } ).catch( ( error ) => {
288
+ reject( error );
289
+ } );
290
+ } else {
291
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
292
+ }
293
+ } );
294
+ }
295
+
296
+ /**
297
+ * Used to add the specified value to a set.
298
+ *
299
+ * @method
300
+ * @param {string} key
301
+ * @param {string} value
302
+ * @returns {Promise}
303
+ * @public
304
+ */
305
+ addToSet( key, value ) {
306
+ return new Promise( ( resolve, reject ) => {
307
+ if ( this.#isOperational === true ) {
308
+ let commandAddToSet = [ redis.cacheCommands.ADD_TO_SET, key, tools.stringifyJSON( value ) ];
309
+ this.#redisClient.executeCommands( [ commandAddToSet ] ).then( () => {
310
+ resolve();
311
+ } ).catch( ( error ) => {
312
+ reject( error );
313
+ } );
314
+ } else {
315
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
316
+ }
317
+ } );
318
+ }
319
+
320
+ /**
321
+ * Used to add multiple values to multiple sets in one transactional request.
322
+ * <br/>
323
+ * NOTE: The two arrays of keys and values must have correct index relations (i.e. first pair on keys[0] and values[0] and so on)!
324
+ *
325
+ * @method
326
+ * @param {string[]} keys
327
+ * @param {string[]} values
328
+ * @returns {Promise}
329
+ * @public
330
+ */
331
+ addToSetMulti( keys, values ) {
332
+ return new Promise( ( resolve, reject ) => {
333
+ if ( this.#isOperational === true ) {
334
+ let commands = [];
335
+ _.forEach( keys, ( key, idx ) => {
336
+ commands.push( [ redis.cacheCommands.ADD_TO_SET, key, tools.stringifyJSON( values[ idx ] ) ] );
337
+ } );
338
+ this.#redisClient.executeCommands( commands ).then( () => {
339
+ resolve();
340
+ } ).catch( ( error ) => {
341
+ reject( error );
342
+ } );
343
+ } else {
344
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
345
+ }
346
+ } );
347
+ }
348
+
349
+ /**
350
+ * Used to check if the provided value is member of the specified set.
351
+ *
352
+ * @method
353
+ * @param {string} setName
354
+ * @param {string} value
355
+ * @returns {Promise<boolean>}
356
+ * @public
357
+ */
358
+ isSetMember( setName, value ) {
359
+ return new Promise( ( resolve, reject ) => {
360
+ if ( this.#isOperational === true ) {
361
+ let commandIsSetMember = [ redis.cacheCommands.IS_SET_MEMBER, setName, value ];
362
+ this.#redisClient.executeCommands( [ commandIsSetMember ] ).then( ( results ) => {
363
+ results = results[ 0 ];
364
+ let result = !!( results && results.length > 1 && results[ 1 ] === 1 );
365
+ resolve( result );
366
+ } ).catch( ( error ) => {
367
+ reject( error );
368
+ } );
369
+ } else {
370
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
371
+ }
372
+ } );
373
+ }
374
+
375
+ /**
376
+ * Used to get all elements of a set.
377
+ *
378
+ * @method
379
+ * @param {string} key
380
+ * @returns {Promise<Object[]>}
381
+ * @public
382
+ */
383
+ membersOfSet( key ) {
384
+ return new Promise( ( resolve, reject ) => {
385
+ if ( this.#isOperational === true ) {
386
+ let commandMembersOfSet = [ redis.cacheCommands.GET_ALL_FROM_SET, key ];
387
+ this.#redisClient.executeCommands( [ commandMembersOfSet ] ).then( ( results ) => {
388
+ results = results[ 0 ];
389
+ let parsedResults = ( results && results.length > 1 && results[ 1 ] ) ? results[ 1 ] : [];
390
+ resolve( parsedResults );
391
+ } ).catch( ( error ) => {
392
+ reject( error );
393
+ } );
394
+ } else {
395
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
396
+ }
397
+ } );
398
+ }
399
+
400
+ /**
401
+ * Used to get a union of all elements in the list of sets.
402
+ *
403
+ * @method
404
+ * @param {string[]} keys
405
+ * @returns {Promise<Object[]>}
406
+ * @public
407
+ */
408
+ unionOfSets( keys ) {
409
+ return new Promise( ( resolve, reject ) => {
410
+ if ( this.#isOperational === true ) {
411
+ let commandUnionOfSets = _.concat( [ redis.cacheCommands.UNION_OF_SETS ], keys );
412
+ this.#redisClient.executeCommands( [ commandUnionOfSets ] ).then( ( results ) => {
413
+ results = results[ 0 ];
414
+ let parsedResults = ( results && results.length > 1 && results[ 1 ] ) ? results[ 1 ] : [];
415
+ resolve( parsedResults );
416
+ } ).catch( ( error ) => {
417
+ reject( error );
418
+ } );
419
+ } else {
420
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
421
+ }
422
+ } );
423
+ }
424
+
425
+ /**
426
+ * Used to set a single hash field.
427
+ *
428
+ * @method
429
+ * @param {string} key
430
+ * @param {string} name
431
+ * @param {*} value
432
+ * @returns {Promise}
433
+ * @public
434
+ */
435
+ hashSetField( key, name, value ) {
436
+ return new Promise( ( resolve, reject ) => {
437
+ if ( this.#isOperational === true ) {
438
+ let commandHashSetField = [ redis.cacheCommands.HASH_SET_MANY, key, name, tools.stringifyJSON( value ) ];
439
+ this.#redisClient.executeCommands( [ commandHashSetField ] ).then( () => {
440
+ resolve();
441
+ } ).catch( ( error ) => {
442
+ reject( error );
443
+ } );
444
+ } else {
445
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
446
+ }
447
+ } );
448
+ }
449
+
450
+ /**
451
+ * Used to set multiple hash fields.
452
+ *
453
+ * @method
454
+ * @param {string} key
455
+ * @param {Object[]} fields
456
+ * @param {string} fields[].name
457
+ * @param {*} fields[].value
458
+ * @returns {Promise}
459
+ * @public
460
+ */
461
+ hashSetFields( key, fields ) {
462
+ return new Promise( ( resolve, reject ) => {
463
+ if ( this.#isOperational === true ) {
464
+ let commandHashSetFields = [ redis.cacheCommands.HASH_SET_MANY, key ];
465
+ _.forEach( fields, ( field ) => {
466
+ commandHashSetFields.push( field.name );
467
+ commandHashSetFields.push( _.isObjectLike( field.value ) ? tools.stringifyJSON( field.value ) : field.value );
468
+ } );
469
+ this.#redisClient.executeCommands( [ commandHashSetFields ] ).then( () => {
470
+ resolve();
471
+ } ).catch( ( error ) => {
472
+ reject( error );
473
+ } );
474
+ } else {
475
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
476
+ }
477
+ } );
478
+ }
479
+
480
+ /**
481
+ * Used to get a single field from a hash.
482
+ *
483
+ * @method
484
+ * @param {string} key
485
+ * @param {string} field
486
+ * @return {Promise}
487
+ * @public
488
+ */
489
+ hashGetField( key, field ) {
490
+ return new Promise( ( resolve, reject ) => {
491
+ if ( this.#isOperational === true ) {
492
+ let commandHashGetField = [ redis.cacheCommands.HASH_GET, key, field ];
493
+ this.#redisClient.executeCommands( [ commandHashGetField ] ).then( ( results ) => {
494
+ results = results[ 0 ];
495
+ resolve( ( results && results.length > 1 && _.isString( results[ 1 ] ) ) ? tools.parseJSON( results[ 1 ] ) : null );
496
+ } ).catch( ( error ) => {
497
+ reject( error );
498
+ } );
499
+ } else {
500
+ reject( exceptions.raise( exceptions.exceptionCode.E_GEN_SYSTEM_CACHE_UNAVAILABLE ) );
501
+ }
502
+ } );
503
+ }
504
+ }
505
+
506
+ const instance = new CommonMemoryCache();
507
+ module.exports = Object.freeze( instance );
@@ -0,0 +1,146 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: © 2021 Boris Kostadinov <kostadinov.boris@gmail.com>
3
+ * SPDX-License-Identifier: ICU
4
+ */
5
+
6
+ const _ = require( "lodash" );
7
+ const tools = require( "#tools" );
8
+
9
+ /**
10
+ * @typedef {string} EnvironmentVariable
11
+ */
12
+
13
+ /**
14
+ * @typedef {NodeJS.Process} Environment
15
+ * @property {ProcessEnv} env
16
+ * @property {EnvironmentVariable} env.TI_GCLOUD_API_KEY
17
+ * @property {EnvironmentVariable} env.TI_GCLOUD_ENABLED
18
+ * @property {EnvironmentVariable} env.TI_GCLOUD_PROJECT_ID
19
+ * @property {EnvironmentVariable} env.TI_INSTANCE_CLASS
20
+ * @property {EnvironmentVariable} env.TI_INSTANCE_CONFIG
21
+ * @property {EnvironmentVariable} env.TI_INSTANCE_ID
22
+ * @property {EnvironmentVariable} env.TI_INSTANCE_NAME
23
+ * @property {EnvironmentVariable} env.TI_LOG_CONSOLE_ENABLED
24
+ * @property {EnvironmentVariable} env.TI_LOG_MIN_LEVEL
25
+ * @property {EnvironmentVariable} env.TI_LOG_USED_JSON
26
+ * @property {EnvironmentVariable} env.TI_OPERATION_MODE
27
+ */
28
+
29
+ /**
30
+ * @typedef {string} CronString
31
+ */
32
+
33
+ /**
34
+ * @typedef {Object} SettingsMain
35
+ * @property {SettingsAuditing} auditing
36
+ * @property {SettingsGcloudIntegration} gcloudIntegration
37
+ * @property {SettingsMemoryCache} memoryCache
38
+ * @property {SettingsMessageExchange} messageExchange
39
+ * @property {SettingsServiceConfig} serviceConfig
40
+ * @property {string} operationMode
41
+ */
42
+
43
+ /**
44
+ * @typedef {Object} SettingsAuditing
45
+ * @property {boolean} logConsoleEnabled
46
+ * @property {boolean} logDetails
47
+ * @property {TiLogSeverity} logMinLevel
48
+ * @property {boolean} logUsesJSON
49
+ */
50
+
51
+ /**
52
+ * @typedef {Object} SettingsGcloudIntegration
53
+ * @property {string} apiKey
54
+ * @property {string} projectID
55
+ */
56
+
57
+ /**
58
+ * @typedef {Object} SettingsMemoryCache
59
+ * @property {string} authKey
60
+ * @property {number} redisDB
61
+ * @property {string} redisHost
62
+ * @property {number} redisPort
63
+ */
64
+
65
+ /**
66
+ * @typedef {Object} SettingsMessageExchange
67
+ * @property {string} messageQueuePrefix
68
+ * @property {string} messageStore
69
+ * @property {boolean} traceLogEnabled
70
+ */
71
+
72
+ /**
73
+ * @typedef {Object} SettingsServiceConfig
74
+ * @property {number} executionTimeout
75
+ * @property {string} healthCheckAddress
76
+ * @property {CronString} healthCheckInterval
77
+ * @property {number} healthCheckTimeout
78
+ * @property {string} serviceRegistryAddress
79
+ */
80
+
81
+ /**
82
+ * Enum for listing all system settings.
83
+ *
84
+ * @readonly
85
+ * @enum {string} Keys of this ENUM are strings.
86
+ */
87
+ let settingsEnum = tools.enum( {
88
+ AUDITING_LOG_CONSOLE_ENABLED: [ "auditing.logConsoleEnabled", "logConsoleEnabled", "" ],
89
+ AUDITING_LOG_DETAILS: [ "auditing.logDetails", "logDetails", "" ],
90
+ AUDITING_LOG_MIN_LEVEL: [ "auditing.logMinLevel", "logMinLevel", "" ],
91
+ AUDITING_LOG_USES_JSON: [ "auditing.logUsesJSON", "logUsesJSON", "" ],
92
+ GCLOUD_API_KEY: [ "gcloudIntegration.apiKey", "apiKey", "" ],
93
+ GCLOUD_PROJECT_ID: [ "gcloudIntegration.projectID", "projectID", "" ],
94
+ MEMORY_CACHE_AUTH_KEY: [ "memoryCache.authKey", "authKey", "" ],
95
+ MEMORY_CACHE_REDIS_DB: [ "memoryCache.redisDB", "redisDB", "" ],
96
+ MEMORY_CACHE_REDIS_HOST: [ "memoryCache.redisHost", "redisHost", "" ],
97
+ MEMORY_CACHE_REDIS_PORT: [ "memoryCache.redisPort", "redisPort", "" ],
98
+ MESSAGE_EXCHANGE_QUEUE_PREFIX: [ "messageExchange.messageQueuePrefix", "messageQueuePrefix", "" ],
99
+ MESSAGE_EXCHANGE_STORE: [ "messageExchange.messageStore", "messageStore", "" ],
100
+ MESSAGE_EXCHANGE_TRACE_LOG_ENABLED: [ "messageExchange.traceLogEnabled", "traceLogEnabled", "" ],
101
+ SERVICE_EXECUTION_TIMEOUT: [ "serviceConfig.executionTimeout", "executionTimeout", "" ],
102
+ SERVICE_HEALTH_CHECK_ADDRESS: [ "serviceConfig.healthCheckAddress", "healthCheckAddress", "" ],
103
+ SERVICE_HEALTH_CHECK_INTERVAL: [ "serviceConfig.healthCheckInterval", "healthCheckInterval", "" ],
104
+ SERVICE_HEALTH_CHECK_TIMEOUT: [ "serviceConfig.healthCheckTimeout", "healthCheckTimeout", "" ],
105
+ SERVICE_REGISTRY_ADDRESS: [ "serviceConfig.serviceRegistryAddress", "serviceRegistryAddress", "" ],
106
+ OPERATION_MODE: [ "operationMode", "operationMode", "" ]
107
+ } );
108
+
109
+ /**
110
+ * @typedef {string} TiSetting
111
+ */
112
+ module.exports.setting = settingsEnum;
113
+
114
+ /** @type {SettingsMain} */
115
+ const settings = require( "#settings" );
116
+
117
+ // override remaining settings with ENV variables (if provided):
118
+ if ( settings.auditing ) {
119
+ settings.auditing.logMinLevel = ( process.env.TI_LOG_MIN_LEVEL !== undefined ) ? process.env.TI_LOG_CONSOLE_ENABLED : settings.auditing.logMinLevel;
120
+ settings.auditing.logConsoleEnabled = ( process.env.TI_LOG_CONSOLE_ENABLED !== undefined ) ? tools.toBool( process.env.TI_LOG_CONSOLE_ENABLED ) : settings.auditing.logConsoleEnabled;
121
+ settings.auditing.logUsesJSON = ( process.env.TI_LOG_USED_JSON !== undefined ) ? tools.toBool( process.env.TI_LOG_USED_JSON ) : settings.auditing.logUsesJSON;
122
+ }
123
+
124
+ // make sure GCloud is enabled before trying to setup it:
125
+ if ( process.env.TI_GCLOUD_ENABLED === true && settings.gcloudIntegration ) {
126
+ settings.gcloudIntegration.apiKey = ( process.env.TI_GCLOUD_API_KEY !== undefined ) ? process.env.TI_GCLOUD_API_KEY : settings.gcloudIntegration.apiKey;
127
+ settings.gcloudIntegration.projectID = ( process.env.TI_GCLOUD_PROJECT_ID !== undefined ) ? process.env.TI_GCLOUD_PROJECT_ID : settings.gcloudIntegration.projectID;
128
+ }
129
+
130
+ settings.operationMode = process.env.TI_OPERATION_MODE || settings.operationMode;
131
+
132
+ // prevent further modifications to the settings object:
133
+ Object.freeze( settings );
134
+
135
+ /**
136
+ * A standard getter method for fetching a setting.
137
+ *
138
+ * @method
139
+ * @param {string|TiSetting} setting Specifies either a dot-separated JSON path of the setting, or is a Setting from the settings enum.
140
+ * @param {*} [defaultValue] The default value to be returned if the setting is not found in the current configuration.
141
+ * @returns {*}
142
+ * @public
143
+ */
144
+ module.exports.getSetting = ( setting, defaultValue ) => {
145
+ return _.get( settings, setting, defaultValue );
146
+ };