@ti-engine/core 1.1.1 → 1.1.2

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
@@ -1,5 +1,17 @@
1
1
  # ti-engine changelog
2
2
 
3
+ ## Version 1.1.2
4
+
5
+ * feat(localization): add new functionality for localization based on labels and system language. It is currently utilized by the `exceptions` module for localizing the exception descriptions. The new `localization` module can also be accessed externally in the implementing application's files via standard import
6
+ * feat(config): add new setting `localization.labelsPath` that specifies the file path for the localization labels
7
+ * feat(config): add new setting `localization.language` that specifies the language to be used for the labels
8
+ * feat(config): add new ENV variable `TI_LOCALIZATION_LABELS_PATH` that controls the `localization.labelsPath` setting
9
+ * feat(config): add new ENV variable `TI_LOCALIZATION_LANGUAGE` that controls the `localization.language` setting
10
+ * feat(logger): log exception label instead of system-level description
11
+ * fix(start instance): fix the order of ENV loading in the `start-instance.js` script. It will now properly load the `.env` file first and then proceed with any configuration overrides in `config` module
12
+ * fix(service provider): normalize service file paths on dynamic service handler loading
13
+ * build(npm): update npm dependencies to their latest versions
14
+
3
15
  ## Version 1.1.1
4
16
 
5
17
  * feat(config): add new ENV variable `TI_AUDITING_LOG_DETAILS` that controls the `auditing.logDetails` setting
package/README.md CHANGED
@@ -6,10 +6,6 @@ Flexible framework for the creation of microservices with [node.js](https://node
6
6
 
7
7
  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**. The architectural concept of the framework is based on a standard _messaging system_ that allows for certain customization but also provides predictability and traceability of its behavior.
8
8
 
9
- Being a messaging system, the **ti-engine** relies on a message broker for the actual exchange of messages between microservice instances. The default implementation of the framework uses [Redis](https://redis.io/) cache, however, you could create your own implementation using something like [Rabbit MQ](https://www.rabbitmq.com/). See the [Advanced topics](#advanced-topics) section of this documentation for guides on how to do this.
10
-
11
- Please be aware, that this framework is under active development and will expand in the near future. Also, this documentation is still in the process of being created and refined. Make sure to keep an eye on the changes in case you want to use it in the meantime.
12
-
13
9
  ## Why ti-engine?
14
10
 
15
11
  The framework is created based on a decade of professional experience with the utilized technologies and architectural approach. It's primary goal is to provide you with a lightweight and flexible solution that can help you build quickly a microservice ecosystem with any degree of size and complexity.
@@ -25,6 +21,10 @@ This is what you gain by using **ti-engine** in your project:
25
21
 
26
22
  These are just some benefits **ti-engine** offers. Get to know it better to find out more ways in which it can help you improve productivity.
27
23
 
24
+ ## Overview
25
+
26
+ Being a messaging system, the **ti-engine** relies on a message broker for the actual exchange of messages between microservice instances. The default implementation of the framework uses [Redis](https://redis.io/) cache, however, you could create your own implementation using something like [Rabbit MQ](https://www.rabbitmq.com/). See the [Advanced topics](#advanced-topics) section of this documentation for guides on how to do this.
27
+
28
28
  ## Prerequisites & installation
29
29
 
30
30
  In order to run the basic ti-engine framework you will need a couple of things:
@@ -0,0 +1,65 @@
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
+ }
65
+ }
package/bin/settings.json CHANGED
@@ -11,6 +11,10 @@
11
11
  "logName": "ti-engine",
12
12
  "projectID": ""
13
13
  },
14
+ "localization": {
15
+ "labelsPath": "../core/bin/localization/labels.json",
16
+ "language": "en"
17
+ },
14
18
  "memoryCache": {
15
19
  "authKey": null,
16
20
  "redisDB": 0,
@@ -7,12 +7,13 @@
7
7
 
8
8
  const _ = require( "lodash" );
9
9
  const path = require( "path" );
10
- const tools = require( "#tools" );
11
- const logger = require( "#logger" );
12
10
 
13
- // load any ENV variables defined in a .env file:
11
+ // load any ENV variables defined in a .env file - before including any framework files:
14
12
  require( "dotenv" ).config( { path: path.join( process.cwd(), ".env" ) } );
15
13
 
14
+ const tools = require( "#tools" );
15
+ const logger = require( "#logger" );
16
+
16
17
  // configure the current instance variables before requiring any platform modules and store the necessary ones in memory cache:
17
18
  process.env.TI_INSTANCE_ID = "ti-" + tools.getUUID();
18
19
  process.env.TI_INSTANCE_CLASS = process.env.TI_INSTANCE_CLASS || "";
@@ -138,7 +138,7 @@ class ServiceProvider extends ServiceConsumer {
138
138
  /** @type {ServiceHandlerMethod} */
139
139
  let serviceHandler = null;
140
140
  if ( serviceDefinition.serviceFile ) {
141
- let serviceFilePath = path.join( process.cwd(), serviceDefinition.serviceFile );
141
+ let serviceFilePath = path.normalize( path.join( process.cwd(), serviceDefinition.serviceFile ) );
142
142
  try {
143
143
  serviceHandler = require( serviceFilePath ).service;
144
144
  } catch ( error ) {
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@ti-engine/core",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
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": "ISC",
7
7
  "exports": {
8
8
  "./exceptions": "./utils/exceptions.js",
9
+ "./localization": "./utils/localization.js",
9
10
  "./logger": "./utils/logger.js",
10
11
  "./service-consumer": "./components/service-consumer.js",
11
12
  "./service-instance": "./components/service-instance.js",
@@ -22,6 +23,7 @@
22
23
  "#default-message-sender": "./components/exchange/default/default-message-sender.js",
23
24
  "#exceptions": "./utils/exceptions.js",
24
25
  "#gcloud-integration": "./integrations/gcloud-integration.js",
26
+ "#localization": "./utils/localization.js",
25
27
  "#logger": "./utils/logger.js",
26
28
  "#message-dispatcher": "./components/exchange/message-dispatcher.js",
27
29
  "#message-exchange": "./components/exchange/message-exchange.js",
@@ -43,7 +45,7 @@
43
45
  "dependencies": {
44
46
  "blake2": "^5.0.0",
45
47
  "dotenv": "^16.3.1",
46
- "fs-extra": "^11.1.1",
48
+ "fs-extra": "^11.2.0",
47
49
  "lodash": "^4.17.21",
48
50
  "node-schedule": "^2.1.1",
49
51
  "ioredis": "^5.3.2"
@@ -54,7 +56,7 @@
54
56
  },
55
57
  "repository": {
56
58
  "type": "git",
57
- "url": "https://github.com/Belleal/ti-engine.git"
59
+ "url": "git+https://github.com/Belleal/ti-engine.git"
58
60
  },
59
61
  "engines": {
60
62
  "node": ">=14.17.0"
package/utils/config.js CHANGED
@@ -24,6 +24,8 @@ const tools = require( "#tools" );
24
24
  * @property {EnvironmentVariable} env.TI_AUDITING_LOG_DETAILS
25
25
  * @property {EnvironmentVariable} env.TI_AUDITING_LOG_MIN_LEVEL
26
26
  * @property {EnvironmentVariable} env.TI_AUDITING_LOG_USES_JSON
27
+ * @property {EnvironmentVariable} env.TI_LOCALIZATION_LABELS_PATH
28
+ * @property {EnvironmentVariable} env.TI_LOCALIZATION_LANGUAGE
27
29
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_AUTH_KEY
28
30
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_DB
29
31
  * @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_HOST
@@ -43,6 +45,7 @@ const tools = require( "#tools" );
43
45
  * @typedef {Object} SettingsMain
44
46
  * @property {SettingsAuditing} auditing
45
47
  * @property {SettingsGcloudIntegration} gcloudIntegration
48
+ * @property {SettingsLocalization} localization
46
49
  * @property {SettingsMemoryCache} memoryCache
47
50
  * @property {SettingsMessageExchange} messageExchange
48
51
  * @property {SettingsServiceConfig} serviceConfig
@@ -63,6 +66,12 @@ const tools = require( "#tools" );
63
66
  * @property {string} projectID
64
67
  */
65
68
 
69
+ /**
70
+ * @typedef {Object} SettingsLocalization
71
+ * @property {string} labelsPath
72
+ * @property {string} language
73
+ */
74
+
66
75
  /**
67
76
  * @typedef {Object} SettingsMemoryCache
68
77
  * @property {string} authKey
@@ -105,6 +114,8 @@ let settingsEnum = tools.enum( {
105
114
  AUDITING_LOG_USES_JSON: [ "auditing.logUsesJSON", "logUsesJSON", "" ],
106
115
  GCLOUD_API_KEY: [ "gcloudIntegration.apiKey", "apiKey", "" ],
107
116
  GCLOUD_PROJECT_ID: [ "gcloudIntegration.projectID", "projectID", "" ],
117
+ LOCALIZATION_LABELS_PATH: [ "localization.labelsPath", "labelsPath", "" ],
118
+ LOCALIZATION_LANGUAGE: [ "localization.language", "language", "" ],
108
119
  MEMORY_CACHE_AUTH_KEY: [ "memoryCache.authKey", "authKey", "" ],
109
120
  MEMORY_CACHE_REDIS_DB: [ "memoryCache.redisDB", "redisDB", "" ],
110
121
  MEMORY_CACHE_REDIS_HOST: [ "memoryCache.redisHost", "redisHost", "" ],
@@ -140,6 +151,10 @@ if ( settings.auditing ) {
140
151
  settings.auditing.logMinLevel = ( process.env.TI_AUDITING_LOG_MIN_LEVEL !== undefined ) ? process.env.TI_AUDITING_LOG_MIN_LEVEL : settings.auditing.logMinLevel;
141
152
  settings.auditing.logUsesJSON = ( process.env.TI_AUDITING_LOG_USES_JSON !== undefined ) ? tools.toBool( process.env.TI_AUDITING_LOG_USES_JSON ) : settings.auditing.logUsesJSON;
142
153
  }
154
+ if ( settings.localization ) {
155
+ settings.localization.labelsPath = ( process.env.TI_LOCALIZATION_LABELS_PATH !== undefined ) ? process.env.TI_LOCALIZATION_LABELS_PATH : settings.localization.labelsPath;
156
+ settings.localization.language = ( process.env.TI_LOCALIZATION_LANGUAGE !== undefined ) ? process.env.TI_LOCALIZATION_LANGUAGE : settings.localization.language;
157
+ }
143
158
  if ( settings.memoryCache ) {
144
159
  settings.memoryCache.authKey = ( process.env.TI_MEMORY_CACHE_AUTH_KEY !== undefined ) ? process.env.TI_MEMORY_CACHE_AUTH_KEY : settings.memoryCache.authKey;
145
160
  settings.memoryCache.redisDB = ( process.env.TI_MEMORY_CACHE_REDIS_DB !== undefined ) ? process.env.TI_MEMORY_CACHE_REDIS_DB : settings.memoryCache.redisDB;
@@ -0,0 +1,27 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: © 2021-2023 Boris Kostadinov <kostadinov.boris@gmail.com>
3
+ * SPDX-License-Identifier: ICU
4
+ */
5
+
6
+ const _ = require( "lodash" );
7
+ const path = require( "path" );
8
+ const config = require( "#config" );
9
+
10
+ const labelsPath = path.normalize( path.join( process.cwd(), config.getSetting( config.setting.LOCALIZATION_LABELS_PATH ) ) );
11
+ const labels = require( labelsPath );
12
+ const defaultEmptyLabel = "!!! label not found !!!";
13
+
14
+ // prevent further modifications to the labels object:
15
+ Object.freeze( labels );
16
+
17
+ /**
18
+ * Used to return the textual value for a label based on the current system language.
19
+ *
20
+ * @method
21
+ * @param {string} label This should be a dot-separated JSON path string.
22
+ * @returns {string}
23
+ * @public
24
+ */
25
+ module.exports.getLabel = ( label ) => {
26
+ return _.get( labels, label + "." + config.getSetting( config.setting.LOCALIZATION_LANGUAGE ), defaultEmptyLabel );
27
+ };
package/utils/logger.js CHANGED
@@ -6,6 +6,7 @@
6
6
  const _ = require( "lodash" );
7
7
  const tools = require( "#tools" );
8
8
  const exceptions = require( "#exceptions" );
9
+ const localization = require( "#localization" );
9
10
 
10
11
  /**
11
12
  * Enum for specifying the log entry severity. This is based on the Google Stackdriver severity levels.
@@ -52,7 +53,7 @@ module.exports.getSeverityName = ( severity ) => {
52
53
  const exceptionToLog = ( exception ) => {
53
54
  return {
54
55
  exceptionID: exception.id,
55
- description: exception.description,
56
+ description: localization.getLabel( exception.label ),
56
57
  details: !_.isEmpty( exception.data ) ? exception.data : undefined
57
58
  };
58
59
  };