@ti-engine/core 1.3.11 → 1.3.12

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/CHANGELOG.md CHANGED
@@ -2,30 +2,46 @@
2
2
 
3
3
  This document will contain the list of changes made to the framework. The format is based on the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
4
4
 
5
+ ## Version 1.3.12
6
+
7
+ * feat(exceptions): add new exception code `E_COM_SERVICE_EXEC_FAILED`
8
+ * feat(localization): add new public method `getAllLabels`
9
+ * feat(localization): use new `deepFreeze` method to freeze all label trees
10
+ * feat(tools): add new public method `deepFreeze` for freezing an object and all its sub-objects recursively
11
+ * feat(config): use new `deepFreeze` method to freeze all configuration settings
12
+ * docs: add more information about the `localization` module in `README.md` file
13
+ * build(npm): update npm dependencies to their latest versions
14
+
5
15
  ## Version 1.3.11
16
+
6
17
  * feat(tools): add `arrayUniques` method to the tools module that helps extract only the unique array values
7
18
  * fix(start instance): fix `undefined` instance ID in the log message about starting the instance
8
19
 
9
20
  ## Version 1.3.10
21
+
10
22
  * chore: fix various minor issues reported by the linter
11
23
  * build(npm): add more information and options to the `package.json` file
12
24
  * docs: add some JSDoc descriptions to classes and methods
13
25
 
14
26
  ## Version 1.3.9
27
+
15
28
  * feat(exceptions): add new exception code `E_GEN_NOT_INITIALIZED`
16
29
  * docs: fix image links in the `README.md` file
17
30
 
18
31
  ## Version 1.3.8
32
+
19
33
  * fix(tester): fix the relative paths of various files in the tester service. The configuration now assumes that the working directory is the root of the tester package instead of the repository itself
20
34
  * build(npm): update npm dependencies to their latest versions
21
35
  * docs: fix some outdated information in the `README.md` file and add some more details
22
36
 
23
37
  ## Version 1.3.7
38
+
24
39
  * feat(exceptions): add new exception code `E_SEC_UNRECOGNIZED_AUTH_METHOD`
25
40
  * fix(config): fix potential issue with `TI_GCLOUD_ENABLED` parsing as boolean
26
41
  * docs: adjust some of the JSDoc descriptions and definitions
27
42
 
28
43
  ## Version 1.3.6
44
+
29
45
  * feat(exceptions): add new exception code `E_GEN_INVALID_ARGUMENT_TYPE`
30
46
  * feat(exceptions): add public enum with all HTTP codes exported as `httpCode` and typedef `TiHttpCode`. Use it as the type for the `httpCode` exception property
31
47
  * feat(tools): add `description` property to enum objects
@@ -41,19 +57,23 @@ This document will contain the list of changes made to the framework. The format
41
57
  * build(npm)!: bump the minimum supported Node.js version to 18.0.0
42
58
 
43
59
  ## Version 1.3.5
60
+
44
61
  * fix(redis integration): fix a duplicated log entry on connection ready event if multiple observers are registered
45
62
  * feat(service caller)!: change log level of error result in `process` method from `ERROR` to `DEBUG`. Implementers are expected to handle this and decide if the error should be propagated further or not
46
63
  * docs: update and fix various issues with the `README.md` file
47
64
 
48
65
  ## Version 1.3.4
66
+
49
67
  * fix(service instance): fix the way `ServiceConfiguration` is propagated via child classes and remove unnecessary defaults. Also update the relevant JSDoc
50
68
 
51
69
  ## Version 1.3.3
70
+
52
71
  * feat(exceptions): add new parameter `includeData` to `Exception.asJSON` method which allows the exclusion of the data parameter from the returned JSON
53
72
  * feat(exceptions): remove several excessive exception codes that were unlikely to be used
54
73
  * fix(localization): add several missing exception labels
55
74
 
56
75
  ## Version 1.3.2
76
+
57
77
  * feat(exceptions): add a set of new exception codes for the needs of any wrapping `web-server` standard communication
58
78
  * feat(exception)!: change the default prefix path for exception labels to `system.exceptions.`
59
79
  * feat(localization): add an Enum list of all language codes based on ISO 639-1 standard
@@ -67,6 +87,7 @@ This document will contain the list of changes made to the framework. The format
67
87
  * fix(auditing): fix a potential problem with setting the log entry reporter from an ENV variable; instead, the system will now use the `ServiceInstance.instanceID` property
68
88
 
69
89
  ## Version 1.3.1
90
+
70
91
  * feat(service caller): refactor the entire service call execution flow for clarity and better performance
71
92
  * feat(service caller): create a new private class `ServiceCallProcessor` to handle individual service calls in a contained scope
72
93
  * feat(message observer): add new property `priority` to the message observer class. It is used to determine the order in which the observers are notified about the messages
@@ -77,6 +98,7 @@ This document will contain the list of changes made to the framework. The format
77
98
  * fix(redis integration): fix an issue which was setting the client status to `DISCONNECTED` during a normal shut down procedure
78
99
 
79
100
  ## Version 1.3.0
101
+
80
102
  * feat(redis integration)!: change `reconnectOnError` behavior to also resubmit the failed command in case the error was of type `READONLY`
81
103
  * feat(redis integration): improve the reliability and usage of the event notification mechanism for connection observers
82
104
  * feat(redis integration): implement listener to the `end` event on Redis connection to capture when connection can no longer be recovered
@@ -90,25 +112,31 @@ This document will contain the list of changes made to the framework. The format
90
112
  * fix(redis integration): fix broken event propagation on `disrupted` events to some connection observers
91
113
 
92
114
  ## Version 1.2.5
115
+
93
116
  * feat(cache): extend method `expireValue` to work with has set fields as well
94
117
 
95
118
  ## Version 1.2.4
119
+
96
120
  * feat(cache): expose the cache module as export in `package.json`
97
121
  * feat(cache): add method `hashDeleteField` to remove a hash-set field. This implements the `hdel` Redis command
98
122
  * fix(tools): optimize method `stringifyJSON` not to call unnecessary decycling of the value if it's not an object
99
123
  * fix(cache): replace `hmset` with `hset` Redis command in both methods that set hash-set values. Also remove unnecessary `_.isObjectLike` call in `hashSetFields` method
100
124
 
101
125
  ## Version 1.2.3
126
+
102
127
  * feat(start instance): add support for providing a custom path to the `.env` file to be used at service startup as process argument. Accepted arguments are `--env`, `--env-file`, `--dotenv`, `--dotenv-path`, and `-e`. The path itself should be relative to the working directory and should include the file name
103
128
 
104
129
  ## Version 1.2.2
130
+
105
131
  * feat(start instance): change package `dotenv` to `@dotenvx/dotenvx` for loading of ENV variables. The new package supports encrypting the ENV variables. For more information see https://dotenvx.com/docs/
106
132
 
107
133
  ## Version 1.2.1
134
+
108
135
  * feat(localization): add support for adding custom labels to the localization system. These have to follow the same format as the system labels
109
136
  * docs: add section about localization to the `README.md` file
110
137
 
111
138
  ## Version 1.2.0
139
+
112
140
  * feat(config)!: change the setting `localization.labelsPath` to be an array of strings. It can now be used to supply any additional custom labels in one or more files to the framework
113
141
  * feat(message memory cache): implement graceful exception handling during shut down procedure in `receiveMessage` and `sendMessage` methods
114
142
  * fix(default message sender): add missing initialization of the memory cache on enable
@@ -121,21 +149,25 @@ This document will contain the list of changes made to the framework. The format
121
149
  * fix(service executor)!: change the individual service registration process to ensure service registration does actually happen before the service provider finishes its initialization
122
150
 
123
151
  ## Version 1.1.10
152
+
124
153
  * fix(cache): fix redis client creation sequence. It is now created inside the constructor as intended. It still needs to be initialized explicitly using the `initialize` method.
125
154
 
126
155
  ## Version 1.1.9
156
+
127
157
  * feat(redis integration)!: change the way the `redis` client is initialized. Instead of happening automatically on class instantiation, it is now initialized on demand using the `initialize` method.
128
158
  * feat(cache): change the way the main cache instance is initialized in compliance with the new redis integration
129
159
  * feat(message memory cache)!: change the way the message memory cache is initialized in compliance with the new redis integration. The `initialize` method needs to be called explicitly to initialize the cache instance before it can be used.
130
160
  * fix(message dispatcher): fix the way the `messageExchange` is initialized in the `MessageDispatcher` class (was not returning a promise)
131
161
 
132
162
  ## Version 1.1.8
163
+
133
164
  * feat(auditing): change export of the singleton class in an `instance` variable for consistency and clarity
134
165
  * feat(message dispatcher): change export of the singleton class in an `instance` variable for consistency and clarity
135
166
  * feat(cache): change export of the singleton class in an `instance` variable for consistency and clarity
136
167
  * feat(service executor): implement service registration retry policy
137
168
 
138
169
  ## Version 1.1.7
170
+
139
171
  * feat(start instance): add support for the detection of `SIGBREAK` events and graceful shutdown on Windows
140
172
  * feat(service instance)!: prevent the initialization of multiple `ServiceInstance` within the same process
141
173
  * feat(message tracer)!: covert to singleton instance and add initialization method
@@ -145,6 +177,7 @@ This document will contain the list of changes made to the framework. The format
145
177
  * fix(redis integration): update links to official commands documentation
146
178
 
147
179
  ## Version 1.1.6
180
+
148
181
  * feat(start instance): add fail-fast mode as default behavior on promise unhandled rejections
149
182
  * feat(start instance): implement functionality to derive safe default service domain name when none is provided in the configuration
150
183
  * feat(config): add support for new ENV variable `TI_FAIL_FAST_ON_UNHANDLED_OFF` that controls the fail-fast mode
package/README.md CHANGED
@@ -544,4 +544,6 @@ The following is an example of a custom localization file. The names in brackets
544
544
  }
545
545
  ```
546
546
 
547
- The individual languages are specified with a two-letter code according to ISO 639-1. The default language is `en` (English). If you want to use a different language, you can set the `LOCALIZATION_LANGUAGE` setting to the desired language code.
547
+ The individual languages are specified with a two-letter code according to ISO 639-1. The default language is `en` (English). If you want to use a different language, you can set the `LOCALIZATION_LANGUAGE` setting to the desired language code.
548
+
549
+ If you want to localize the system labels of the framework, you can do so by providing a custom localization file with the same structure as the default one but containing only the languages you want to add. For example, the default English label for `E_UNKNOWN_ERROR` is found in JSON path `system.exceptions.0.en`. To add an entry for German, your file needs to contain a `system.exceptions.0.de` property. The localization module will handle the rest. You can use the same approach to modify the existing English labels as well. The full list of system labels is found in the `bin/localization/labels.json` file. Avoid modifying the default file since it might get overwritten by future updates.
@@ -70,6 +70,9 @@
70
70
  "3007": {
71
71
  "en": "The message exchange is irrevocably broken and cannot be used any longer."
72
72
  },
73
+ "3008": {
74
+ "en": "The execution of a service reported a failure. This might be a business logic error or a system error."
75
+ },
73
76
  "3010": {
74
77
  "en": "Connection retry attempts exceeded the configured limit."
75
78
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ti-engine/core",
3
- "version": "1.3.11",
3
+ "version": "1.3.12",
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
  "keywords": [
6
6
  "microservices",
@@ -59,7 +59,7 @@
59
59
  "dependencies": {
60
60
  "@dotenvx/dotenvx": "^1.51.0",
61
61
  "blake2": "^5.0.0",
62
- "ioredis": "^5.8.0",
62
+ "ioredis": "^5.8.2",
63
63
  "lodash": "^4.17.21",
64
64
  "node-schedule": "^2.1.1"
65
65
  },
package/utils/config.js CHANGED
@@ -185,7 +185,7 @@ if ( tools.toBool( process.env.TI_GCLOUD_ENABLED ) === true && settings.gcloudIn
185
185
  settings.operationMode = process.env.NODE_ENV || settings.operationMode;
186
186
 
187
187
  // Prevent further modifications to the settings object:
188
- Object.freeze( settings );
188
+ tools.deepFreeze( settings );
189
189
 
190
190
  /**
191
191
  * A standard getter method for fetching a setting.
@@ -43,6 +43,7 @@ const exceptionCodeEnum = tools.enum( {
43
43
  E_COM_SERVICE_HANDLER_NOT_FOUND: [ 3005, "service handler not found", "No handler found in the interface for the specified service or service version." ],
44
44
  E_COM_MESSAGE_RECEIVER_UNAVAILABLE: [ 3006, "message receiver unavailable", "The message receiver instance is currently unavailable." ],
45
45
  E_COM_MESSAGE_EXCHANGE_BROKEN: [ 3007, "message exchange broken", "The message exchange is irrevocably broken and cannot be used any longer." ],
46
+ E_COM_SERVICE_EXEC_FAILED: [ 3008, "service exec failed", "The execution of a service reported a failure. This might be a business logic error or a system error." ],
46
47
  E_COM_RETRY_ATTEMPTS_EXCEEDED: [ 3010, "retry attempts exceeded", "Connection retry attempts exceeded the configured limit." ],
47
48
  /** Web server exceptions - codes under 4xxx */
48
49
  E_WEB_INVALID_REQUEST_METHOD: [ 4000, "invalid request method", "The request method is not recognized or not supported." ],
@@ -245,12 +245,7 @@ module.exports.localizationLanguage = localizationLanguageEnum;
245
245
  * @typedef {Object<string, TiLocalizedLabel | TiLabelsTree>} TiLabelsTree
246
246
  */
247
247
 
248
- /**
249
- * @typedef {Object} TiLabels
250
- * @property {TiLabelsTree} labels
251
- */
252
-
253
- /** @type {TiLabels} */
248
+ /** @type {TiLabelsTree} */
254
249
  const labels = require( "#labels" );
255
250
 
256
251
  // Load any custom labels defined in the configuration:
@@ -264,7 +259,7 @@ if ( labelsPaths && _.isArray( labelsPaths ) && labelsPaths.length > 0 ) {
264
259
  }
265
260
 
266
261
  // Prevent further modifications to the TiLabels object:
267
- Object.freeze( labels );
262
+ tools.deepFreeze( labels );
268
263
 
269
264
  /**
270
265
  * Used to return the textual value for a label based on the current system language by default or the specified language code if provided.
@@ -277,4 +272,43 @@ Object.freeze( labels );
277
272
  */
278
273
  module.exports.getLabel = ( label, language ) => {
279
274
  return _.get( labels, label + "." + ( ( language ) ? language : config.getSetting( config.setting.LOCALIZATION_LANGUAGE ) ), defaultEmptyLabel );
275
+ };
276
+
277
+ const labelsCacheByLanguage = new Map();
278
+
279
+ /**
280
+ * Used to return the entire labels tree.
281
+ * <br/>
282
+ * NOTE: The result will be a modified copy of the label tree that has no "language" end-nodes and keeps only the appropriate labels for the requested language.
283
+ * For example, if the original JSON path is "path.to.label.language", the returned path will be just "path.to.label" corresponding to the text label.
284
+ *
285
+ * @method
286
+ * @param {TiLocalizationLanguage} [language] The language code to use for the lookup. If not provided, the current system language will be used.
287
+ * @returns {TiLabelsTree}
288
+ * @public
289
+ */
290
+ module.exports.getAllLabels = ( language ) => {
291
+ const usedLanguage = language || config.getSetting( config.setting.LOCALIZATION_LANGUAGE );
292
+
293
+ if ( labelsCacheByLanguage.has( usedLanguage ) ) {
294
+ return labelsCacheByLanguage.get( usedLanguage );
295
+ } else {
296
+ const labelsByLanguage = _.cloneDeepWith( labels, ( value ) => {
297
+ if ( _.isPlainObject( value ) ) {
298
+ const values = Object.values( value );
299
+ const isLeaf = values.length > 0 && values.every( v => _.isString( v ) || _.isNil( v ) );
300
+ if ( isLeaf ) {
301
+ // Return only the desired language or default placeholder if missing:
302
+ return _.get( value, usedLanguage, defaultEmptyLabel );
303
+ }
304
+ } else {
305
+ // Return undefined to let lodash handle default deep cloning for non-leaves:
306
+ return undefined;
307
+ }
308
+ } );
309
+
310
+ tools.deepFreeze( labelsByLanguage );
311
+ labelsCacheByLanguage.set( usedLanguage, labelsByLanguage );
312
+ return labelsByLanguage;
313
+ }
280
314
  };
package/utils/tools.js CHANGED
@@ -35,6 +35,27 @@ module.exports.getUUID = () => {
35
35
  return crypto.randomUUID( { disableEntropyCache: true } );
36
36
  };
37
37
 
38
+ /**
39
+ * Used to deep-freeze an object.
40
+ *
41
+ * @method
42
+ * @param {Object} object
43
+ * @param {WeakSet} [seen]
44
+ * @return {Object}
45
+ * @public
46
+ */
47
+ module.exports.deepFreeze = ( object, seen = new WeakSet() ) => {
48
+ if ( object === null || typeof object !== "object" || seen.has( object ) ) {
49
+ return object;
50
+ } else {
51
+ seen.add( object );
52
+ _.forOwn( object, ( value ) => {
53
+ module.exports.deepFreeze( value, seen );
54
+ } );
55
+ return Object.freeze( object );
56
+ }
57
+ };
58
+
38
59
  /**
39
60
  * Used to create a custom Enum list.
40
61
  *