@ti-engine/core 1.3.1 → 1.3.5

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.
@@ -1,65 +1,99 @@
1
- {
2
- "labels": {
3
- "general": {
4
- "exceptions": {
5
- "0": {
6
- "en": "Unidentified error encountered or unrecognized exception code provided."
7
- },
8
- "1000": {
9
- "en": "Error thrown by internal JS source."
10
- },
11
- "1001": {
12
- "en": "Attempt to construct an abstract class detected."
13
- },
14
- "1002": {
15
- "en": "Attempt to call an abstract method detected."
16
- },
17
- "1003": {
18
- "en": "Invalid or no service domain name provided at microservice startup."
19
- },
20
- "1004": {
21
- "en": "The system cache required for proper engine operation is unavailable."
22
- },
23
- "1005": {
24
- "en": "The provided service handler is not a proper function."
25
- },
26
- "1006": {
27
- "en": "The requested feature is not supported by current configuration or version."
28
- },
29
- "2000": {
30
- "en": "Invalid authorization token provided."
31
- },
32
- "2001": {
33
- "en": "Invalid or expired session encountered."
34
- },
35
- "2002": {
36
- "en": "Attempt for unauthorized access detected."
37
- },
38
- "2003": {
39
- "en": "The system detected tampering with the message received via message exchange."
40
- },
41
- "3000": {
42
- "en": "General error during cross-application communication."
43
- },
44
- "3001": {
45
- "en": "The message sender instance is currently unavailable."
46
- },
47
- "3002": {
48
- "en": "The execution of a service could not complete within the allowed timeout."
49
- },
50
- "3003": {
51
- "en": "The specified service is not found in the service registry."
52
- },
53
- "3004": {
54
- "en": "The specified service is not found in the service definition interface."
55
- },
56
- "3005": {
57
- "en": "No handler found in the interface for the specified service or service version."
58
- },
59
- "3010": {
60
- "en": "Connection retry attempts exceeded the configured limit."
61
- }
62
- }
63
- }
64
- }
1
+ {
2
+ "system": {
3
+ "exceptions": {
4
+ "0": {
5
+ "en": "Unidentified error encountered or unrecognized exception code provided."
6
+ },
7
+ "1000": {
8
+ "en": "Error thrown by internal JS source."
9
+ },
10
+ "1001": {
11
+ "en": "Attempt to construct an abstract class detected."
12
+ },
13
+ "1002": {
14
+ "en": "Attempt to call an abstract method detected."
15
+ },
16
+ "1003": {
17
+ "en": "Invalid or no service domain name provided at microservice startup."
18
+ },
19
+ "1004": {
20
+ "en": "The system cache required for proper engine operation is unavailable."
21
+ },
22
+ "1005": {
23
+ "en": "The provided service handler is not a proper function."
24
+ },
25
+ "1006": {
26
+ "en": "The requested feature is not supported by current configuration or version."
27
+ },
28
+ "2000": {
29
+ "en": "Invalid authorization token provided."
30
+ },
31
+ "2001": {
32
+ "en": "Invalid or expired session encountered."
33
+ },
34
+ "2002": {
35
+ "en": "Attempt for unauthorized access detected."
36
+ },
37
+ "2003": {
38
+ "en": "The system detected tampering with the message received via message exchange."
39
+ },
40
+ "3000": {
41
+ "en": "General error during cross-application communication."
42
+ },
43
+ "3001": {
44
+ "en": "The message sender instance is currently unavailable."
45
+ },
46
+ "3002": {
47
+ "en": "The execution of a service could not complete within the allowed timeout."
48
+ },
49
+ "3003": {
50
+ "en": "The specified service is not found in the service registry."
51
+ },
52
+ "3004": {
53
+ "en": "The specified service is not found in the service definition interface."
54
+ },
55
+ "3005": {
56
+ "en": "No handler found in the interface for the specified service or service version."
57
+ },
58
+ "3006": {
59
+ "en": "The message receiver instance is currently unavailable."
60
+ },
61
+ "3007": {
62
+ "en": "The message exchange is irrevocably broken and cannot be used any longer."
63
+ },
64
+ "3010": {
65
+ "en": "Connection retry attempts exceeded the configured limit."
66
+ },
67
+ "4000": {
68
+ "en": "The request method is not recognized or not supported."
69
+ },
70
+ "4001": {
71
+ "en": "The request URI is not recognized or not supported."
72
+ },
73
+ "4002": {
74
+ "en": "The request body is not recognized or not supported."
75
+ },
76
+ "4003": {
77
+ "en": "The request query is not recognized or not supported."
78
+ },
79
+ "4004": {
80
+ "en": "The request headers are not recognized or not supported."
81
+ },
82
+ "4005": {
83
+ "en": "The request parameters are not recognized or not supported."
84
+ },
85
+ "4006": {
86
+ "en": "The request format is not recognized or not supported."
87
+ },
88
+ "4007": {
89
+ "en": "The request content type is not recognized or not supported."
90
+ },
91
+ "4008": {
92
+ "en": "The request content length is not recognized or not supported."
93
+ },
94
+ "4009": {
95
+ "en": "The request content encoding is not recognized or not supported."
96
+ }
97
+ }
98
+ }
65
99
  }
@@ -11,9 +11,10 @@ const tools = require( "#tools" );
11
11
  const logger = require( "#logger" );
12
12
  const config = require( "#config" );
13
13
  const gcloud = require( "#gcloud-integration" );
14
+ const ServiceInstance = require( "#service-instance" );
14
15
 
15
16
  /**
16
- * @typedef {Object} LogEntry
17
+ * @typedef {Object} TiLogEntry
17
18
  * @property {string} _id Unique identifier that can be used to identify the document in a NoSQL database.
18
19
  * @property {TiLogSeverity} severity The log severity level.
19
20
  * @property {string} thread The categorization of the log message.
@@ -59,19 +60,19 @@ class Auditing {
59
60
  */
60
61
  log( message, severity = logger.logSeverity.DEFAULT, thread = "main", data = {} ) {
61
62
  try {
62
- // log entries bellow the min allowed level will be ignored:
63
+ // Log entries below the minimum allowed level will be directly ignored:
63
64
  if ( severity >= config.getSetting( config.setting.AUDITING_LOG_MIN_LEVEL ) ) {
64
- // obscure any passwords that might have landed in the data object;
65
- // also make sure to convert a potential Error object to a JSON:
65
+ // Obscure any passwords that might have landed in the data object;
66
+ // Also make sure to convert a potential Error object to a JSON:
66
67
  let copyOfData = ( config.getSetting( config.setting.AUDITING_LOG_DETAILS ) === true ) ? _.cloneDeep( data ) : undefined;
67
68
  let logEntry = Auditing.#createLogEntry( severity, thread, message, copyOfData );
68
69
 
69
- // make sure there is a console available:
70
+ // Make sure there is a console available (especially important for Cloud or containerized environments):
70
71
  if ( config.getSetting( config.setting.AUDITING_LOG_CONSOLE_ENABLED ) === true && console ) {
71
72
  Auditing.#logToConsole( logEntry );
72
73
  }
73
74
 
74
- // if this is an actual error, then send it to GCloud error reporting system as well:
75
+ // If this is an actual error, then send it to GCloud error reporting system as well:
75
76
  if ( logEntry.severity >= logger.logSeverity.WARNING && data instanceof Error && gcloud.isEnabled() ) {
76
77
  gcloud.reportError( data );
77
78
  }
@@ -91,14 +92,14 @@ class Auditing {
91
92
  * @param {string} thread
92
93
  * @param {string} message
93
94
  * @param {Object} data
94
- * @returns {LogEntry}
95
+ * @returns {TiLogEntry}
95
96
  * @private
96
97
  */
97
98
  static #createLogEntry( severity, thread, message, data ) {
98
99
  let currentDate = new Date();
99
100
  let logDate = tools.getUTCDateString( currentDate );
100
101
  let logTime = tools.getUTCTimeString( currentDate, true );
101
- let reporter = process.env.TI_INSTANCE_ID;
102
+ let reporter = ServiceInstance.instanceID;
102
103
 
103
104
  return {
104
105
  _id: `${ logDate }-${ logTime }-${ thread }-${ reporter }-${ logger.getSeverityName( severity ) }-${ tools.getUUID() }`,
@@ -112,13 +113,13 @@ class Auditing {
112
113
  }
113
114
 
114
115
  /**
115
- * Used to write the log entries to the system console (i.e. STD OUT and STD ERR).
116
+ * Used to write the log entries to the system console (i.e., STD OUT and STD ERR).
116
117
  * <br/>
117
118
  * NOTE: There was an issue in previous Node versions with console that can crash the application if the number of
118
- * outputs exceeds several thousands per second. To be monitored and adjusted as necessary!
119
+ * outputs exceeds several thousands per second. To be monitored and adjusted as necessary!
119
120
  *
120
121
  * @method
121
- * @param {LogEntry} logEntry
122
+ * @param {TiLogEntry} logEntry
122
123
  * @private
123
124
  */
124
125
  static #logToConsole( logEntry ) {
@@ -140,7 +141,7 @@ class Auditing {
140
141
  * Used to format a log entry for the Node console.
141
142
  *
142
143
  * @method
143
- * @param {LogEntry} logEntry
144
+ * @param {TiLogEntry} logEntry
144
145
  * @returns {string}
145
146
  * @private
146
147
  */
@@ -153,7 +154,7 @@ class Auditing {
153
154
  * Used to format a log entry data payload for the Node console.
154
155
  *
155
156
  * @method
156
- * @param {LogEntry} logEntry
157
+ * @param {TiLogEntry} logEntry
157
158
  * @returns {string}
158
159
  * @private
159
160
  */
@@ -48,7 +48,7 @@ const messageDispatcher = require( "#message-dispatcher" );
48
48
 
49
49
  /**
50
50
  * @typedef {Object} ServiceCallResult
51
- * @property {Object|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
51
+ * @property {Exception|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
52
52
  * @property {boolean} isSuccessful A flag indicating if this service call can be considered successful or not.
53
53
  * @property {Object|string|undefined} payload The payload containing the results from the service call processing. If a string, it is ID of the payload in the memory cache instead.
54
54
  */
@@ -187,7 +187,7 @@ class ServiceCallProcessor {
187
187
  } ).catch( ( error ) => {
188
188
  clearTimeout( this.#timeoutHandle );
189
189
  this.#isProcessed = true;
190
- logger.log( `Error during service call execution!`, logger.logSeverity.ERROR, error );
190
+ logger.log( `Error during service call execution!`, logger.logSeverity.DEBUG, error );
191
191
  return {
192
192
  isSuccessful: false,
193
193
  exception: exceptions.raise( error ),
@@ -293,7 +293,7 @@ class ServiceCaller extends MessageObserver {
293
293
  * @public
294
294
  */
295
295
  executeServiceCall( serviceAddress, serviceParams, serviceExecContext ) {
296
- return new Promise( ( resolve, reject ) => {
296
+ return new Promise( ( resolve ) => {
297
297
  let processor = new ServiceCallProcessor( serviceAddress, serviceParams, serviceExecContext );
298
298
  this.#addProcessor( processor.messageID, processor );
299
299
  processor.process().then( ( serviceCallResult ) => {
@@ -32,9 +32,9 @@ class ServiceConsumer extends ServiceInstance {
32
32
  /**
33
33
  * @constructor
34
34
  * @param {string} serviceDomainName The service domain name for this service instance.
35
- * @param {Object} [serviceConfig={}] The JSON configuration for this service.
35
+ * @param {ServiceConfiguration} [serviceConfig] The JSON configuration for this service.
36
36
  */
37
- constructor( serviceDomainName, serviceConfig = {} ) {
37
+ constructor( serviceDomainName, serviceConfig ) {
38
38
  super( serviceDomainName, serviceConfig );
39
39
 
40
40
  // make sure this abstract class cannot be instantiated:
@@ -17,7 +17,7 @@ const messageDispatcher = require( "#message-dispatcher" );
17
17
 
18
18
  /**
19
19
  * @typedef {Object} ServiceConfiguration
20
- * @property {ServiceDefinition[]} services A list of service definitions to be registered with the {@link ServiceProvider}.
20
+ * @property {ServiceDefinition[]} [services] A list of service definitions to be registered with the {@link ServiceProvider}.
21
21
  */
22
22
 
23
23
  /**
@@ -42,9 +42,9 @@ class ServiceInstance {
42
42
  /**
43
43
  * @constructor
44
44
  * @param {string} serviceDomainName The service domain name for this service instance.
45
- * @param {Object} [serviceConfig={}] The JSON configuration for this service.
45
+ * @param {ServiceConfiguration} [serviceConfig={ services: [] }] The JSON configuration for this service.
46
46
  */
47
- constructor( serviceDomainName, serviceConfig = {} ) {
47
+ constructor( serviceDomainName, serviceConfig = { services: [] } ) {
48
48
  // Ensure this abstract class cannot be instantiated:
49
49
  if ( new.target === ServiceInstance ) {
50
50
  throw exceptions.raise( exceptions.exceptionCode.E_GEN_ABSTRACT_CLASS_INIT, { name: this.constructor.name } );
@@ -37,9 +37,9 @@ class ServiceProvider extends ServiceConsumer {
37
37
  /**
38
38
  * @constructor
39
39
  * @param {string} serviceDomainName The service domain name for this service instance.
40
- * @param {Object} [serviceConfig={}] The JSON configuration for this service.
40
+ * @param {ServiceConfiguration} [serviceConfig] The JSON configuration for this service.
41
41
  */
42
- constructor( serviceDomainName, serviceConfig = {} ) {
42
+ constructor( serviceDomainName, serviceConfig ) {
43
43
  super( serviceDomainName, serviceConfig );
44
44
 
45
45
  // make sure this abstract class cannot be instantiated:
@@ -118,7 +118,7 @@ class RedisClient {
118
118
  /* Public interface */
119
119
 
120
120
  /**
121
- * Used to return the Redis client identifier.
121
+ * Used to return the Redis client identifier assigned internally.
122
122
  *
123
123
  * @property
124
124
  * @returns {string}
@@ -129,7 +129,7 @@ class RedisClient {
129
129
  }
130
130
 
131
131
  /**
132
- * Used to return the Redis client ID.
132
+ * Used to return the client ID assigned by the Redis server.
133
133
  *
134
134
  * @property
135
135
  * @returns {number}
@@ -195,9 +195,9 @@ class RedisClient {
195
195
  // Fetch the server information and store it:
196
196
  return this.#fetchServerInfo();
197
197
  } ).then( () => {
198
- return this.#getClientId();
198
+ return this.#getClientID();
199
199
  } ).then( ( clientID ) => {
200
- // Store the client ID:
200
+ // Store the connection ID:
201
201
  this.#redisClientID = clientID;
202
202
  resolve();
203
203
  } ).catch( ( error ) => {
@@ -476,10 +476,12 @@ class RedisClient {
476
476
 
477
477
  this.#redisConnection.once( "ready", () => {
478
478
  this.#clientStatus = clientStatusEnum.CONNECTED;
479
+ logger.log( `Connection to Redis server '${ this.#redisConnection.options.host }:${ this.#redisConnection.options.port }' established by client '${ this.identifier }' and is ready to be used.`, logger.logSeverity.INFO );
479
480
  this.#notifyConnectionObservers();
480
481
 
481
482
  this.#redisConnection.on( "ready", () => {
482
483
  this.#clientStatus = clientStatusEnum.CONNECTED;
484
+ logger.log( `Connection to Redis server '${ this.#redisConnection.options.host }:${ this.#redisConnection.options.port }' reestablished by client '${ this.identifier }' and is ready to be used.`, logger.logSeverity.INFO );
483
485
  this.#notifyConnectionObservers();
484
486
  } );
485
487
 
@@ -515,14 +517,13 @@ class RedisClient {
515
517
  */
516
518
  #notifyConnectionObservers() {
517
519
  // Notify all connection observers about the event:
518
- _.forEach( this.#connectionObservers, ( connectionObservers ) => {
520
+ _.forEach( this.#connectionObservers, ( connectionObserver ) => {
519
521
  if ( this.#clientStatus === clientStatusEnum.CONNECTED ) {
520
- logger.log( `Connection to Redis server ${ this.#redisConnection.options.host }:${ this.#redisConnection.options.port } (re)established by client '${ this.identifier }' and is ready to be used.`, logger.logSeverity.INFO );
521
- connectionObservers.onConnectionRecovered( this.#clientIdentifier );
522
+ connectionObserver.onConnectionRecovered( this.#clientIdentifier );
522
523
  } else if ( this.#clientStatus === clientStatusEnum.DISRUPTED ) {
523
- connectionObservers.onConnectionDisrupted( this.#clientIdentifier );
524
+ connectionObserver.onConnectionDisrupted( this.#clientIdentifier );
524
525
  } else if ( this.#clientStatus === clientStatusEnum.DISCONNECTED ) {
525
- connectionObservers.onConnectionLost( this.#clientIdentifier );
526
+ connectionObserver.onConnectionLost( this.#clientIdentifier );
526
527
  }
527
528
  } );
528
529
  }
@@ -574,7 +575,7 @@ class RedisClient {
574
575
  * @returns {Promise<number>}
575
576
  * @private
576
577
  */
577
- #getClientId() {
578
+ #getClientID() {
578
579
  let commandArguments = [ "client", "id" ];
579
580
  return this.callCommand( commandArguments ).then( ( clientID ) => Number( clientID ) );
580
581
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ti-engine/core",
3
- "version": "1.3.1",
3
+ "version": "1.3.5",
4
4
  "description": "The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.",
5
5
  "author": "Boris Kostadinov <kostadinov.boris@gmail.com>",
6
6
  "license": "GPL-3.0-or-later",
package/utils/config.js CHANGED
@@ -73,7 +73,7 @@ const tools = require( "#tools" );
73
73
  /**
74
74
  * @typedef {Object} SettingsLocalization
75
75
  * @property {Array<string>} labelsPath
76
- * @property {string} language
76
+ * @property {TiLocalizationLanguage} language
77
77
  */
78
78
 
79
79
  /**
@@ -113,7 +113,7 @@ const tools = require( "#tools" );
113
113
  * @readonly
114
114
  * @enum {string} Keys of this ENUM are strings.
115
115
  */
116
- let settingsEnum = tools.enum( {
116
+ const settingsEnum = tools.enum( {
117
117
  AUDITING_LOG_CONSOLE_ENABLED: [ "auditing.logConsoleEnabled", "logConsoleEnabled", "" ],
118
118
  AUDITING_LOG_DETAILS: [ "auditing.logDetails", "logDetails", "" ],
119
119
  AUDITING_LOG_MIN_LEVEL: [ "auditing.logMinLevel", "logMinLevel", "" ],
@@ -152,7 +152,7 @@ module.exports.setting = settingsEnum;
152
152
  /** @type {SettingsMain} */
153
153
  const settings = require( "#settings" );
154
154
 
155
- // override remaining settings with ENV variables (if provided):
155
+ // Override the remaining settings with ENV variables (if provided):
156
156
  if ( settings.auditing ) {
157
157
  settings.auditing.logConsoleEnabled = ( process.env.TI_AUDITING_LOG_CONSOLE_ENABLED !== undefined ) ? tools.toBool( process.env.TI_AUDITING_LOG_CONSOLE_ENABLED ) : settings.auditing.logConsoleEnabled;
158
158
  settings.auditing.logDetails = ( process.env.TI_AUDITING_LOG_DETAILS !== undefined ) ? tools.toBool( process.env.TI_AUDITING_LOG_DETAILS ) : settings.auditing.logDetails;
@@ -160,7 +160,7 @@ if ( settings.auditing ) {
160
160
  settings.auditing.logUsesJSON = ( process.env.TI_AUDITING_LOG_USES_JSON !== undefined ) ? tools.toBool( process.env.TI_AUDITING_LOG_USES_JSON ) : settings.auditing.logUsesJSON;
161
161
  }
162
162
  if ( settings.localization ) {
163
- settings.localization.labelsPath = ( process.env.TI_LOCALIZATION_LABELS_PATH !== undefined ) ? process.env.TI_LOCALIZATION_LABELS_PATH : settings.localization.labelsPath;
163
+ settings.localization.labelsPath = ( process.env.TI_LOCALIZATION_LABELS_PATH !== undefined ) ? [ process.env.TI_LOCALIZATION_LABELS_PATH ] : settings.localization.labelsPath;
164
164
  settings.localization.language = ( process.env.TI_LOCALIZATION_LANGUAGE !== undefined ) ? process.env.TI_LOCALIZATION_LANGUAGE : settings.localization.language;
165
165
  }
166
166
  if ( settings.memoryCache ) {
@@ -186,7 +186,7 @@ if ( process.env.TI_GCLOUD_ENABLED === true && settings.gcloudIntegration ) {
186
186
 
187
187
  settings.operationMode = process.env.NODE_ENV || settings.operationMode;
188
188
 
189
- // prevent further modifications to the settings object:
189
+ // Prevent further modifications to the settings object:
190
190
  Object.freeze( settings );
191
191
 
192
192
  /**