@things-factory/integration-base 7.0.0-alpha.8 → 7.0.1-alpha.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.
Files changed (50) hide show
  1. package/dist-server/engine/connection-manager.js +37 -6
  2. package/dist-server/engine/connection-manager.js.map +1 -1
  3. package/dist-server/engine/connector/graphql-connector.js +6 -6
  4. package/dist-server/engine/connector/graphql-connector.js.map +1 -1
  5. package/dist-server/engine/connector/operato-connector.js +19 -22
  6. package/dist-server/engine/connector/operato-connector.js.map +1 -1
  7. package/dist-server/engine/connector/proxy-connector.js +44 -0
  8. package/dist-server/engine/connector/proxy-connector.js.map +1 -0
  9. package/dist-server/engine/edge-client.js +38 -0
  10. package/dist-server/engine/edge-client.js.map +1 -0
  11. package/dist-server/engine/index.js +1 -0
  12. package/dist-server/engine/index.js.map +1 -1
  13. package/dist-server/engine/task/script.js +1 -0
  14. package/dist-server/engine/task/script.js.map +1 -1
  15. package/dist-server/engine/types.js.map +1 -1
  16. package/dist-server/service/connection/connection-mutation.js +4 -8
  17. package/dist-server/service/connection/connection-mutation.js.map +1 -1
  18. package/dist-server/service/connection/connection-query.js +17 -14
  19. package/dist-server/service/connection/connection-query.js.map +1 -1
  20. package/dist-server/service/connection/connection-subscription.js +1 -1
  21. package/dist-server/service/connection/connection-subscription.js.map +1 -1
  22. package/dist-server/service/connection/connection-type.js +32 -8
  23. package/dist-server/service/connection/connection-type.js.map +1 -1
  24. package/dist-server/service/scenario-instance/scenario-instance-type.js +12 -4
  25. package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
  26. package/dist-server/tsconfig.tsbuildinfo +1 -1
  27. package/helps/integration/concept/script-internal-variables.ja.md +21 -1
  28. package/helps/integration/concept/script-internal-variables.ko.md +17 -0
  29. package/helps/integration/concept/script-internal-variables.md +18 -0
  30. package/helps/integration/concept/script-internal-variables.ms.md +19 -1
  31. package/helps/integration/concept/script-internal-variables.zh.md +18 -0
  32. package/helps/integration/task/script.ja.md +1 -1
  33. package/helps/integration/task/script.ko.md +1 -1
  34. package/helps/integration/task/script.md +1 -1
  35. package/helps/integration/task/script.ms.md +1 -1
  36. package/helps/integration/task/script.zh.md +1 -1
  37. package/package.json +10 -10
  38. package/server/engine/connection-manager.ts +49 -7
  39. package/server/engine/connector/graphql-connector.ts +8 -10
  40. package/server/engine/connector/operato-connector.ts +22 -32
  41. package/server/engine/connector/proxy-connector.ts +53 -0
  42. package/server/engine/edge-client.ts +45 -0
  43. package/server/engine/index.ts +1 -0
  44. package/server/engine/task/script.ts +1 -0
  45. package/server/engine/types.ts +45 -46
  46. package/server/service/connection/connection-mutation.ts +9 -29
  47. package/server/service/connection/connection-query.ts +13 -12
  48. package/server/service/connection/connection-subscription.ts +1 -1
  49. package/server/service/connection/connection-type.ts +53 -41
  50. package/server/service/scenario-instance/scenario-instance-type.ts +13 -5
@@ -17,8 +17,28 @@
17
17
  - email: ユーザーの電子メール
18
18
  - userType: ユーザータイプ
19
19
 
20
- - lng: シナリオを開始するユーザーのブラウザで使用されている言語(例:en-US、ko-KR など)。 ユーザーのブラウザを介さないリクエストを処理する場合、この組み込み変数は提供されない場合があります。
20
+ - lng: シナリオを開始するユーザーのブラウザで使用されている言語(例:en-US、ko-KR など)。
21
+
22
+ - ユーザーのブラウザを介さないリクエストを処理する場合、この組み込み変数は提供されない場合があります。
21
23
 
22
24
  - variables: シナリオ呼び出し時に呼び出し元から受け取るオブジェクト。
23
25
 
24
26
  - data: シナリオの実行中に生成された各ステップの結果データ。
27
+
28
+ - logger (only for script):スクリプト内で必要に応じてログを残すことができる
29
+ - ログレベル:info, warn, error
30
+
31
+ ```javascript
32
+ // 組み込み変数と変数の使用例
33
+ const username = user ? user.name : '不明なユーザー'
34
+ const companyName = domain ? domain.name : '不明な会社'
35
+
36
+ // info レベルのログを残す例(組み込み変数と変数を使用)
37
+ logger.info(`ユーザー '${username}' が '${companyName}' からシステムにアクセスしました。`)
38
+
39
+ // warn レベルのログを残す例(組み込み変数と変数を使用)
40
+ logger.warn(`ユーザー '${username}' が許可されていない操作を試みました。`)
41
+
42
+ // error レベルのログを残す例(組み込み変数と変数を使用)
43
+ logger.error(`ユーザー '${username}' のデータ処理中にエラーが発生しました。`)
44
+ ```
@@ -16,3 +16,20 @@
16
16
  - 사용자 브라우저를 통하지 않은 요청을 처리할 때에는 이 내장변수가 제공되지 않을 수 있다.
17
17
  - variables : 시나리오 호출 시점에 호출자로부터 전달받은 오브젝트
18
18
  - data: 시나리오 실행과정에 생성된 각 스텝의 결과 데이타
19
+ - logger: 스크립트 내에서 필요시 로그를 남길 수 있도록 제공된다
20
+ - log levels : info, warn, error
21
+
22
+ ```javascript
23
+ // 내장 변수와 변수 사용 예시
24
+ const username = user ? user.name : 'Unknown User'
25
+ const companyName = domain ? domain.name : 'Unknown Company'
26
+
27
+ // info 레벨의 로그를 남기는 예시 (내장 변수 및 변수 사용)
28
+ logger.info(`User '${username}' from '${companyName}' accessed the system.`)
29
+
30
+ // warn 레벨의 로그를 남기는 예시 (내장 변수 및 변수 사용)
31
+ logger.warn(`User '${username}' attempted an unauthorized action.`)
32
+
33
+ // error 레벨의 로그를 남기는 예시 (내장 변수 및 변수 사용)
34
+ logger.error(`An error occurred while processing data for user '${username}'.`)
35
+ ```
@@ -22,3 +22,21 @@ In script-type task properties (Script, SQL, GraphQL Query/Mutation, Log, etc.),
22
22
  - variables: An object received from the caller at the time of scenario invocation.
23
23
 
24
24
  - data: Results data generated for each step during scenario execution.
25
+
26
+ - logger (only for script): Provided to leave logs as needed within the script
27
+ - log levels: info, warn, error
28
+
29
+ ```javascript
30
+ // Example of using built-in variables and variables
31
+ const username = user ? user.name : 'Unknown User'
32
+ const companyName = domain ? domain.name : 'Unknown Company'
33
+
34
+ // Example of leaving a log at the info level (using built-in variables and variables)
35
+ logger.info(`User '${username}' from '${companyName}' accessed the system.`)
36
+
37
+ // Example of leaving a log at the warn level (using built-in variables and variables)
38
+ logger.warn(`User '${username}' attempted an unauthorized action.`)
39
+
40
+ // Example of leaving a log at the error level (using built-in variables and variables)
41
+ logger.error(`An error occurred while processing data for user '${username}'.`)
42
+ ```
@@ -17,4 +17,22 @@ Dalam sifat tugas jenis skrip (Skrip, SQL, Pertanyaan/Mutasi GraphQL, Log, dsb.)
17
17
  - email: E-mel pengguna
18
18
  - userType: Jenis pengguna
19
19
 
20
- - lng: Bahasa yang digunakan oleh pelayar pengguna ketika memulakan senario (contohnya, en-US, ko
20
+ - lng: Bahasa yang digunakan oleh pelayar pengguna ketika memulakan senario (contohnya, en-US, ko-KR)
21
+
22
+ - logger (only for script): menyediakan kemampuan untuk meninggalkan log apabila diperlukan dalam skrip
23
+ - tahap log: info, warn, error
24
+
25
+ ```javascript
26
+ // contoh penggunaan variable bawaan dan variable
27
+ const username = user ? user.name : 'Pengguna Tidak Diketahui'
28
+ const companyName = domain ? domain.name : 'Syarikat Tidak Diketahui'
29
+
30
+ // contoh meninggalkan log tahap info (menggunakan variable bawaan dan variable)
31
+ logger.info(`Pengguna '${username}' dari '${companyName}' mengakses sistem.`)
32
+
33
+ // contoh meninggalkan log tahap warn (menggunakan variable bawaan dan variable)
34
+ logger.warn(`Pengguna '${username}' mencuba tindakan yang tidak dibenarkan.`)
35
+
36
+ // contoh meninggalkan log tahap error (menggunakan variable bawaan dan variable)
37
+ logger.error(`Terjadi kesalahan semasa memproses data untuk pengguna '${username}'.`)
38
+ ```
@@ -22,3 +22,21 @@
22
22
  - variables: 在方案调用时从调用者那里接收的对象
23
23
 
24
24
  - data: 在方案执行过程中生成的每个步骤的结果数据
25
+
26
+ - logger(only for script):在脚本中需要时可以留下日志
27
+ - 日志级别:info, warn, error
28
+
29
+ ```javascript
30
+ // 内置变量和变量使用示例
31
+ const username = user ? user.name : '未知用户'
32
+ const companyName = domain ? domain.name : '未知公司'
33
+
34
+ // 记录 info 级别日志的示例(使用内置变量和变量)
35
+ logger.info(`用户 '${username}' 从 '${companyName}' 访问了系统。`)
36
+
37
+ // 记录 warn 级别日志的示例(使用内置变量和变量)
38
+ logger.warn(`用户 '${username}' 尝试了未授权的操作。`)
39
+
40
+ // 记录 error 级别日志的示例(使用内置变量和变量)
41
+ logger.error(`处理用户 '${username}' 的数据时发生错误。`)
42
+ ```
@@ -6,7 +6,7 @@
6
6
 
7
7
  - script
8
8
  - JavaScript 構文で記述します。
9
- - グローバルオブジェクトは、対応する[シナリオコンテキスト](../concept/scenario-context.md)からのデータと変数を含むシンプルなオブジェクトです。つまり、スクリプト内では、シナリオの[スクリプト内蔵変数](../concept/script-internal-variables.md)から特別な修飾子なしで、または`this`アクセサを介してデータ、変数、ドメイン、ユーザー、lng 変数を使用できます。
9
+ - グローバルオブジェクトは、対応する[シナリオコンテキスト](../concept/scenario-context.md)からのデータと変数を含むシンプルなオブジェクトです。つまり、スクリプト内では、シナリオの[スクリプト内蔵変数](../concept/script-internal-variables.md)から特別な修飾子なしで、または`this`アクセサを介して data, variables, domain, user, lng, logger 変数を使用できます。
10
10
  - タスクの実行結果は`return`構文を介して返されます。
11
11
  - スクリプト内のグ
12
12
 
@@ -6,7 +6,7 @@ Javascript Syntax로 작성된 script를 실행하여 그 결과를 리턴하는
6
6
 
7
7
  - script
8
8
  - javascript systax로 작성한다.
9
- - global 오브젝트는 해당된 [Scenario Context](../concept/scenario-context.md)중 data 와 variables 를 가진 단순한 오브젝트이다. 즉, 스크립트 내에서 해당된 시나리오의 [스크립트 내장변수](../concept/script-internal-variables.md)인 data, variables, domain, user, lng 변수를 특별한 수식자없이 또는 this 접근자를 통해서 사용할 수 있다.
9
+ - global 오브젝트는 해당된 [Scenario Context](../concept/scenario-context.md)중 data 와 variables 를 가진 단순한 오브젝트이다. 즉, 스크립트 내에서 해당된 시나리오의 [스크립트 내장변수](../concept/script-internal-variables.md)인 data, variables, domain, user, lng, logger 변수를 특별한 수식자없이 또는 this 접근자를 통해서 사용할 수 있다.
10
10
  - 태스크의 수행 결과는 return 신택스를 통해서 반환된다.
11
11
  - script 내에서는 global 오브젝트가 data와 variables 등 [스크립트 내장변수](../concept/script-internal-variables.md)로 한정되므로, 대부분의 시스템 관련된 기능은 사용할 수 없는 sandbox 환경이라고 이해하고, 단순한 연산정도의 기능을 구현하는 것을 권장한다.
12
12
  - [Node Sandbox](https://medium.com/@devnullnor/a-secure-node-sandbox-f23b9fc9f2b0)
@@ -6,7 +6,7 @@ This is a task that executes a script written in JavaScript syntax and returns t
6
6
 
7
7
  - script
8
8
  - Write in JavaScript syntax.
9
- - The global object is a simple object that contains data and variables from the corresponding [Scenario Context](../concept/scenario-context.md). In other words, within the script, you can use the data, variables, domain, user, and lng variables from the scenario's [Script Built-in Variables](../concept/script-internal-variables.md) without any special modifiers or through the `this` accessor.
9
+ - The global object is a simple object that contains data and variables from the corresponding [Scenario Context](../concept/scenario-context.md). In other words, within the script, you can use the data, variables, domain, user, logger and lng variables from the scenario's [Script Built-in Variables](../concept/script-internal-variables.md) without any special modifiers or through the `this` accessor.
10
10
  - The task's execution result is returned through the `return` syntax.
11
11
  - Since the global object within the script is limited to data and variables, as well as other [Script Built-in Variables](../concept/script-internal-variables.md), consider it a sandbox environment where most system-related functionalities are unavailable. It's recommended to implement simple operations.
12
12
  - [Node Sandbox](https://medium.com/@devnullnor/a-secure-node-sandbox-f23b9fc9f2b0)
@@ -6,7 +6,7 @@ Ini adalah tugas yang menjalankan skrip yang ditulis dalam sintaks JavaScript da
6
6
 
7
7
  - skrip
8
8
  - Ditulis dalam sintaks JavaScript.
9
- - Objek global adalah objek sederhana yang mengandungi data dan pembolehubah dari [Konteks Senario](../concept/scenario-context.md) yang berkaitan. Dengan kata lain, dalam skrip ini, anda boleh menggunakan data, pembolehubah, domain, pengguna, dan pembolehubah lng dari [Pembolehubah Terbina Dalam Skrip](../concept/script-internal-variables.md) senario tanpa modifier khas atau melalui aksesori `this`.
9
+ - Objek global adalah objek sederhana yang mengandungi data dan pembolehubah dari [Konteks Senario](../concept/scenario-context.md) yang berkaitan. Dengan kata lain, dalam skrip ini, anda boleh menggunakan data, variables, domain, user, lng, logger dari [Pembolehubah Terbina Dalam Skrip](../concept/script-internal-variables.md) senario tanpa modifier khas atau melalui aksesori `this`.
10
10
  - Hasil pelaksanaan tugas dikembalikan melalui sintaks `return`.
11
11
  - Oleh kerana objek global dalam skrip terhad kepada data dan pembolehubah, serta Pembolehubah Terbina Dalam Skrip yang lain, pertimbangkan ia sebagai persekitaran sandbox di mana kebanyakan fungsi berkaitan sistem tidak tersedia. Disarankan untuk melaksanakan operasi yang ringkas.
12
12
  - [Node Sandbox](https://medium.com/@devnullnor/a-secure-node-sandbox-f23b9fc9f2b0)
@@ -6,7 +6,7 @@
6
6
 
7
7
  - 脚本
8
8
  - 以 JavaScript 语法编写。
9
- - 全局对象是一个简单的对象,包含来自相应[场景上下文](../concept/scenario-context.md)的数据和变量。换句话说,在脚本内部,您可以使用来自场景的[脚本内置变量](../concept/script-internal-variables.md)(例如 data、variables、domain、user 和 lng 变量)而无需任何特殊修饰符,或者通过`this`访问器。
9
+ - 全局对象是一个简单的对象,包含来自相应[场景上下文](../concept/scenario-context.md)的数据和变量。换句话说,在脚本内部,您可以使用来自场景的[脚本内置变量](../concept/script-internal-variables.md)(例如 data、variables、domain、user, logger 和 lng 变量)而无需任何特殊修饰符,或者通过`this`访问器。
10
10
  - 任务的执行结果通过`return`语法返回。
11
11
  - 由于脚本内的全局对象仅限于数据和变量以及其他[脚本内置变量](../concept/script-internal-variables.md),请将其视为一个沙盒环境,在该环境中大多数与系统相关的功能不可用。建议实现简单的操作。
12
12
  - [Node Sandbox](https://medium.com/@devnullnor/a-secure-node-sandbox-f23b9fc9f2b0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-base",
3
- "version": "7.0.0-alpha.8",
3
+ "version": "7.0.1-alpha.0",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -26,13 +26,13 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@apollo/client": "^3.6.9",
29
- "@things-factory/api": "^7.0.0-alpha.8",
30
- "@things-factory/auth-base": "^7.0.0-alpha.8",
31
- "@things-factory/env": "^7.0.0-alpha.0",
32
- "@things-factory/oauth2-client": "^7.0.0-alpha.8",
33
- "@things-factory/scheduler-client": "^7.0.0-alpha.8",
34
- "@things-factory/shell": "^7.0.0-alpha.8",
35
- "@things-factory/utils": "^7.0.0-alpha.0",
29
+ "@things-factory/api": "^7.0.1-alpha.0",
30
+ "@things-factory/auth-base": "^7.0.1-alpha.0",
31
+ "@things-factory/env": "^7.0.1-alpha.0",
32
+ "@things-factory/oauth2-client": "^7.0.1-alpha.0",
33
+ "@things-factory/scheduler-client": "^7.0.1-alpha.0",
34
+ "@things-factory/shell": "^7.0.1-alpha.0",
35
+ "@things-factory/utils": "^7.0.1-alpha.0",
36
36
  "async-mqtt": "^2.5.0",
37
37
  "chance": "^1.1.11",
38
38
  "cross-fetch": "^3.0.4",
@@ -41,7 +41,7 @@
41
41
  "node-fetch": "^2.6.0",
42
42
  "promise-socket": "^7.0.0",
43
43
  "readline": "^1.3.0",
44
- "vm2": "3.9.11"
44
+ "vm2": "^3.9.11"
45
45
  },
46
- "gitHead": "b4981ea2721e7eaf4dbd618b6c77316ebc000ee5"
46
+ "gitHead": "d18cdb7648bd2003f11278ec7bc8df74edbd31fc"
47
47
  }
@@ -5,6 +5,7 @@ import { Domain, getRepository, pubsub, PubSubLogTransport } from '@things-facto
5
5
 
6
6
  import { Connection, ConnectionStatus } from '../service'
7
7
  import { Connector } from './types'
8
+ import { ProxyConnector } from './connector/proxy-connector'
8
9
 
9
10
  const { combine, timestamp, splat, printf } = format
10
11
  const debug = require('debug')('things-factory:integration-base:connections')
@@ -17,7 +18,8 @@ const systemTimestamp = format((info, opts) => {
17
18
 
18
19
  export class ConnectionManager {
19
20
  private static connectors: { [propName: string]: Connector } = {}
20
- private static connections = {}
21
+ private static connections: { [domainId: string]: { [name: string]: any } } = {}
22
+ private static entities = {}
21
23
  private static logFormat = printf(({ level, message, timestamp }) => {
22
24
  return `${timestamp} ${level}: ${message}`
23
25
  })
@@ -43,7 +45,7 @@ export class ConnectionManager {
43
45
  const CONNECTIONS = (
44
46
  await getRepository(Connection).find({
45
47
  where: { active: true },
46
- relations: ['domain', 'creator', 'updater']
48
+ relations: ['domain', 'edge', 'creator', 'updater']
47
49
  })
48
50
  ).map(connection => {
49
51
  var params = {}
@@ -63,12 +65,21 @@ export class ConnectionManager {
63
65
  ConnectionManager.logger.info('Initializing ConnectionManager...')
64
66
 
65
67
  return await Promise.all(
66
- Object.keys(ConnectionManager.connectors).map(type => {
67
- var connector = ConnectionManager.connectors[type]
68
+ [...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {
69
+ const connector = 'proxy-connector' ? ProxyConnector.instance : ConnectionManager.getConnector(type)
70
+
68
71
  ConnectionManager.logger.info(`Connector '${type}' started to ready`)
69
72
 
70
73
  return connector
71
- .ready(CONNECTIONS.filter(connection => connection.type == type) as any)
74
+ .ready(
75
+ CONNECTIONS.filter(connection => {
76
+ if (type == 'proxy-connector') {
77
+ return !!connection.edge
78
+ } else {
79
+ return !connection.edge && connection.type == type
80
+ }
81
+ }) as any
82
+ )
72
83
  .catch(error => {
73
84
  ConnectionManager.logger.error(error.message)
74
85
  })
@@ -103,6 +114,14 @@ export class ConnectionManager {
103
114
  delete ConnectionManager.connectors[type]
104
115
  }
105
116
 
117
+ static getConnections() {
118
+ return ConnectionManager.connections
119
+ }
120
+
121
+ static getEntities() {
122
+ return ConnectionManager.entities
123
+ }
124
+
106
125
  static getConnectionInstance(connection: Connection): any {
107
126
  const { domain, name } = connection
108
127
  return ConnectionManager.connections[domain.id]?.[name]
@@ -119,6 +138,11 @@ export class ConnectionManager {
119
138
  return connection
120
139
  }
121
140
 
141
+ static getConnectionInstanceEntityByName(domain: Domain, name: string): any {
142
+ const entities = ConnectionManager.entities[domain.id]
143
+ return entities?.[name]
144
+ }
145
+
122
146
  static getConnectionInstances(domain: Domain): { [connectionName: string]: any } {
123
147
  const connections = ConnectionManager.connections[domain.id]
124
148
 
@@ -127,6 +151,14 @@ export class ConnectionManager {
127
151
  }
128
152
  }
129
153
 
154
+ static getConnectionInstanceEntities(domain: Domain): { [connectionName: string]: any } {
155
+ const connections = ConnectionManager.entities[domain.id]
156
+
157
+ return {
158
+ ...connections
159
+ }
160
+ }
161
+
130
162
  static addConnectionInstance(connection: Connection, instance: any) {
131
163
  const { domain, name } = connection
132
164
 
@@ -135,7 +167,13 @@ export class ConnectionManager {
135
167
  connections = ConnectionManager.connections[domain.id] = {}
136
168
  }
137
169
 
170
+ var entities = ConnectionManager.entities[domain.id]
171
+ if (!entities) {
172
+ entities = ConnectionManager.entities[domain.id] = {}
173
+ }
174
+
138
175
  connections[name] = instance
176
+ entities[name] = connection
139
177
 
140
178
  ConnectionManager.publishState(connection, ConnectionStatus.CONNECTED)
141
179
  debug('add-connection', domain.subdomain, name)
@@ -144,6 +182,8 @@ export class ConnectionManager {
144
182
  static removeConnectionInstance(connection: Connection): any {
145
183
  const { domain, name } = connection
146
184
  var connections = ConnectionManager.connections[domain.id]
185
+ var entities = ConnectionManager.entities[domain.id]
186
+
147
187
  var instance = connections?.[name]
148
188
 
149
189
  if (!connections || !instance) {
@@ -152,6 +192,7 @@ export class ConnectionManager {
152
192
  }
153
193
 
154
194
  delete connections[name]
195
+ delete entities[name]
155
196
 
156
197
  ConnectionManager.publishState(connection, ConnectionStatus.DISCONNECTED)
157
198
  debug('remove-connection', `'${name}' connection is removed from domain '${domain.subdomain}'`)
@@ -159,8 +200,8 @@ export class ConnectionManager {
159
200
  return instance
160
201
  }
161
202
 
162
- static publishState(connection: Connection, state) {
163
- const { domain, id, name, description, type } = connection
203
+ private static async publishState(connection: Connection, state) {
204
+ const { domain, id, name, description, type, edge } = connection
164
205
 
165
206
  pubsub.publish('connection-state', {
166
207
  connectionState: {
@@ -169,6 +210,7 @@ export class ConnectionManager {
169
210
  name,
170
211
  description,
171
212
  type,
213
+ edge,
172
214
  state,
173
215
  timestamp: new Date()
174
216
  }
@@ -23,10 +23,6 @@ const defaultOptions: any = {
23
23
  }
24
24
  }
25
25
 
26
- const cache = new InMemoryCache({
27
- addTypename: false
28
- })
29
-
30
26
  export class GraphqlConnector implements Connector {
31
27
  async ready(connectionConfigs: InputConnection[]) {
32
28
  await Promise.all(connectionConfigs.map(this.connect.bind(this)))
@@ -35,12 +31,12 @@ export class GraphqlConnector implements Connector {
35
31
  }
36
32
 
37
33
  async connect(connection: InputConnection) {
38
- var {
34
+ const {
39
35
  endpoint: uri,
40
36
  params: { authClient }
41
37
  } = connection
42
38
 
43
- var ERROR_HANDLER: any = ({ graphQLErrors, networkError }) => {
39
+ const ERROR_HANDLER: any = ({ graphQLErrors, networkError }) => {
44
40
  if (graphQLErrors)
45
41
  graphQLErrors.map(({ message, locations, path }) => {
46
42
  ConnectionManager.logger.error(`[GraphQL error] Message: ${message}, Location: ${locations}, Path: ${path}`)
@@ -65,6 +61,10 @@ export class GraphqlConnector implements Connector {
65
61
  return forward(operation)
66
62
  })
67
63
 
64
+ const cache = new InMemoryCache({
65
+ addTypename: false
66
+ })
67
+
68
68
  ConnectionManager.addConnectionInstance(
69
69
  connection,
70
70
  new ApolloClient({
@@ -81,13 +81,11 @@ export class GraphqlConnector implements Connector {
81
81
  })
82
82
  )
83
83
 
84
- ConnectionManager.logger.info(
85
- `graphql-connector connection(${connection.name}:${connection.endpoint}) is connected`
86
- )
84
+ ConnectionManager.logger.info(`graphql-connector connection(${connection.name}:${connection.endpoint}) is connected`)
87
85
  }
88
86
 
89
87
  async disconnect(connection: InputConnection) {
90
- var client = ConnectionManager.getConnectionInstance(connection)
88
+ const client = ConnectionManager.getConnectionInstance(connection)
91
89
  client.stop()
92
90
  ConnectionManager.removeConnectionInstance(connection)
93
91
 
@@ -3,7 +3,6 @@ import 'cross-fetch/polyfill'
3
3
  import { ApolloClient, InMemoryCache, createHttpLink, split } from '@apollo/client/core'
4
4
  import { setContext } from '@apollo/client/link/context'
5
5
 
6
- // for subscription
7
6
  import WebSocket from 'ws'
8
7
  import { createClient } from 'graphql-ws'
9
8
  import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
@@ -20,7 +19,7 @@ import { ScenarioInstance } from '../../service/scenario-instance/scenario-insta
20
19
  import { getRepository, GraphqlLocalClient, Domain } from '@things-factory/shell'
21
20
  import { User, checkPermission } from '@things-factory/auth-base'
22
21
 
23
- const debug = require('debug')('things-factory:integration-base:operato-connector-subscription')
22
+ const debug = require('debug')('things-factory:integration-base:operato-connector')
24
23
 
25
24
  const defaultOptions: any = {
26
25
  watchQuery: {
@@ -36,10 +35,6 @@ const defaultOptions: any = {
36
35
  }
37
36
  }
38
37
 
39
- const cache = new InMemoryCache({
40
- addTypename: false
41
- })
42
-
43
38
  export const GRAPHQL_URI = '/graphql'
44
39
  export const SUBSCRIPTION_URI = GRAPHQL_URI
45
40
 
@@ -48,7 +43,6 @@ interface SubscriberData {
48
43
  scenario: any
49
44
  subscriptionObserver: any
50
45
  }
51
- ;``
52
46
 
53
47
  export class OperatoConnector implements Connector {
54
48
  private context: any
@@ -56,11 +50,11 @@ export class OperatoConnector implements Connector {
56
50
  async ready(connectionConfigs: InputConnection[]) {
57
51
  await Promise.all(connectionConfigs.map(this.connect.bind(this)))
58
52
 
59
- ConnectionManager.logger.info('graphql-connector connections are ready')
53
+ ConnectionManager.logger.info('operato-connector connections are ready')
60
54
  }
61
55
 
62
56
  async connect(connection: InputConnection) {
63
- var {
57
+ const {
64
58
  endpoint: uri,
65
59
  params: { authKey, domain, subscriptionHandlers = {} }
66
60
  } = connection
@@ -69,7 +63,7 @@ export class OperatoConnector implements Connector {
69
63
  throw new Error('some connection paramter missing.')
70
64
  }
71
65
 
72
- var domainOwner = await getRepository(User).findOne({
66
+ const domainOwner = await getRepository(User).findOne({
73
67
  where: {
74
68
  id: connection.domain.owner
75
69
  }
@@ -125,20 +119,24 @@ export class OperatoConnector implements Connector {
125
119
  }).concat(httpLink)
126
120
  )
127
121
 
128
- var client = new ApolloClient({
122
+ const cache = new InMemoryCache({
123
+ addTypename: false
124
+ })
125
+
126
+ const client = new ApolloClient({
129
127
  defaultOptions,
130
128
  cache,
131
129
  link: splitLink
132
130
  })
133
131
 
134
- var subscriptions: SubscriberData[] = []
132
+ const subscriptions: SubscriberData[] = []
135
133
  Object.keys(subscriptionHandlers).forEach(async tag => {
136
134
  if (!tag || !subscriptionHandlers[tag]) return
137
135
 
138
- let scenarioName = subscriptionHandlers[tag]
136
+ const scenarioName = subscriptionHandlers[tag]
139
137
 
140
138
  // fetch a scenario
141
- var selectedScenario = await getRepository(Scenario).findOne({
139
+ const selectedScenario = await getRepository(Scenario).findOne({
142
140
  where: {
143
141
  name: scenarioName
144
142
  },
@@ -156,7 +154,7 @@ export class OperatoConnector implements Connector {
156
154
  `
157
155
  })
158
156
 
159
- var subscriptionObserver = subscription.subscribe({
157
+ const subscriptionObserver = subscription.subscribe({
160
158
  next: async data => {
161
159
  debug('received pubsub msg.:', data?.data)
162
160
  await this.runScenario(subscriptions, data?.data?.data)
@@ -169,9 +167,7 @@ export class OperatoConnector implements Connector {
169
167
  }
170
168
  })
171
169
 
172
- ConnectionManager.logger.info(
173
- `(${connection.name}:${connection.endpoint}) subscription closed flag: ${subscriptionObserver.closed}`
174
- )
170
+ ConnectionManager.logger.info(`(${connection.name}:${connection.endpoint}) subscription closed flag: ${subscriptionObserver.closed}`)
175
171
 
176
172
  subscriptions.push({
177
173
  tag,
@@ -184,19 +180,17 @@ export class OperatoConnector implements Connector {
184
180
  client['subscriptions'] = subscriptions
185
181
  ConnectionManager.addConnectionInstance(connection, client)
186
182
 
187
- ConnectionManager.logger.info(
188
- `graphql-connector connection(${connection.name}:${connection.endpoint}) is connected`
189
- )
183
+ ConnectionManager.logger.info(`operato-connector connection(${connection.name}:${connection.endpoint}) is connected`)
190
184
  }
191
185
 
192
186
  async disconnect(connection: InputConnection) {
193
- var client = ConnectionManager.getConnectionInstance(connection)
194
- let subscriptions: SubscriberData[] = client['subscriptions']
187
+ const client = ConnectionManager.getConnectionInstance(connection)
188
+ const subscriptions: SubscriberData[] = client['subscriptions']
195
189
  subscriptions.forEach(subscription => subscription.subscriptionObserver.unsubscribe())
196
190
  client.stop()
197
191
  ConnectionManager.removeConnectionInstance(connection)
198
192
 
199
- ConnectionManager.logger.info(`graphql-connector connection(${connection.name}) is disconnected`)
193
+ ConnectionManager.logger.info(`operato-connector connection(${connection.name}) is disconnected`)
200
194
  }
201
195
 
202
196
  async runScenario(subscriptions: SubscriberData[], variables: any): Promise<ScenarioInstance> {
@@ -207,23 +201,19 @@ export class OperatoConnector implements Connector {
207
201
  throw new Error(`tag is invalid - ${tag}`)
208
202
  }
209
203
 
210
- var scenario = subscriptions.find(subscription => subscription.tag === tag)?.scenario
204
+ const scenario = subscriptions.find(subscription => subscription.tag === tag)?.scenario
211
205
  if (!scenario) {
212
206
  throw new Error(`scenario is not found - ${tag}`)
213
207
  }
214
208
 
215
209
  if (!(await checkPermission(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {
216
210
  const { category, privilege } = scenario.privilege || {}
217
- throw new Error(
218
- `Unauthorized! ${
219
- category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'
220
- } required`
221
- )
211
+ throw new Error(`Unauthorized! ${category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'} required`)
222
212
  }
223
213
 
224
214
  /* create a scenario instance */
225
- let instanceName = scenario.name + '-' + String(Date.now())
226
- var instance = new ScenarioInstance(instanceName, scenario, {
215
+ const instanceName = scenario.name + '-' + String(Date.now())
216
+ const instance = new ScenarioInstance(instanceName, scenario, {
227
217
  user,
228
218
  domain,
229
219
  variables,
@@ -0,0 +1,53 @@
1
+ import { ConnectionManager } from '../connection-manager'
2
+ import { Connector } from '../types'
3
+ import { InputConnection } from '../../service/connection/connection-type'
4
+ import { connectConnections, disconnectConnections } from '../edge-client'
5
+
6
+ /**
7
+ * This connector is a proxy connector installed on the edge server to manage connections from the host.
8
+ * It interacts with connections established on the edge server and provides synchronization functionality.
9
+ */
10
+ export class ProxyConnector implements Connector {
11
+ public static instance = new ProxyConnector()
12
+
13
+ async ready(connectionConfigs: InputConnection[]) {
14
+ await Promise.all(connectionConfigs.map(this.connect.bind(this)))
15
+
16
+ ConnectionManager.logger.info('proxy-connector connections are ready')
17
+ }
18
+
19
+ async connect(connection: InputConnection) {
20
+ // TODO 원래 커넥션과 에지설정을 참고하여, 에지 서버로 CONNECT/DISCONNECT 명령을 보낸다.
21
+ const proxy = {
22
+ disconnect: async () => {
23
+ ConnectionManager.logger.info('[proxy-connector] trying disconnect')
24
+ await disconnectConnections([connection])
25
+ }
26
+ }
27
+
28
+ await connectConnections([connection])
29
+
30
+ ConnectionManager.addConnectionInstance(connection, proxy)
31
+
32
+ ConnectionManager.logger.info(`proxy-connector connection(${connection.name}:${connection.endpoint}) is connected`)
33
+ }
34
+
35
+ async disconnect(connection: InputConnection) {
36
+ const proxy = ConnectionManager.removeConnectionInstance(connection)
37
+ await proxy.disconnect()
38
+
39
+ ConnectionManager.logger.info(`proxy-connector connection(${connection.name}) is disconnected`)
40
+ }
41
+
42
+ get parameterSpec() {
43
+ return []
44
+ }
45
+
46
+ get taskPrefixes() {
47
+ return []
48
+ }
49
+
50
+ get description() {
51
+ return 'Operato Proxy Connector'
52
+ }
53
+ }