@things-factory/integration-base 8.0.0-beta.8 → 8.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.
Files changed (160) hide show
  1. package/dist-server/engine/connector/http-connector.js +1 -1
  2. package/dist-server/engine/connector/http-connector.js.map +1 -1
  3. package/dist-server/engine/connector/index.d.ts +0 -1
  4. package/dist-server/engine/connector/index.js +0 -1
  5. package/dist-server/engine/connector/index.js.map +1 -1
  6. package/dist-server/engine/index.d.ts +0 -1
  7. package/dist-server/engine/index.js +0 -1
  8. package/dist-server/engine/index.js.map +1 -1
  9. package/dist-server/engine/task/headless-post.js +33 -19
  10. package/dist-server/engine/task/headless-post.js.map +1 -1
  11. package/dist-server/engine/task/headless-scrap.js +13 -20
  12. package/dist-server/engine/task/headless-scrap.js.map +1 -1
  13. package/dist-server/tsconfig.tsbuildinfo +1 -1
  14. package/package.json +11 -12
  15. package/server/controllers/index.ts +2 -0
  16. package/server/controllers/publish-data.ts +29 -0
  17. package/server/controllers/scenario-controller.ts +156 -0
  18. package/server/engine/analyzer/analyze-integration.ts +115 -0
  19. package/server/engine/connection-manager.ts +239 -0
  20. package/server/engine/connector/echo-back-connector.ts +51 -0
  21. package/server/engine/connector/echo-back-server.ts +72 -0
  22. package/server/engine/connector/graphql-connector.ts +126 -0
  23. package/server/engine/connector/http-connector.ts +65 -0
  24. package/server/engine/connector/index.ts +12 -0
  25. package/server/engine/connector/mqtt-connector.ts +78 -0
  26. package/server/engine/connector/mssql-connector.ts +152 -0
  27. package/server/engine/connector/mysql-connector.ts +94 -0
  28. package/server/engine/connector/operato-connector.ts +264 -0
  29. package/server/engine/connector/oracle-connector.ts +218 -0
  30. package/server/engine/connector/postgresql-connector.ts +152 -0
  31. package/server/engine/connector/proxy-connector.ts +53 -0
  32. package/server/engine/connector/socket-server.ts +86 -0
  33. package/server/engine/connector/sqlite-connector.ts +69 -0
  34. package/server/engine/edge-client.ts +45 -0
  35. package/server/engine/index.ts +10 -0
  36. package/server/engine/pending-queue.ts +97 -0
  37. package/server/engine/scenario-engine.ts +106 -0
  38. package/server/engine/task/book-up-scenario.ts +73 -0
  39. package/server/engine/task/csv-readline.ts +127 -0
  40. package/server/engine/task/data-accessor.ts +36 -0
  41. package/server/engine/task/data-mapper.ts +47 -0
  42. package/server/engine/task/database-query.ts +56 -0
  43. package/server/engine/task/echo-receive.ts +21 -0
  44. package/server/engine/task/echo-send.ts +32 -0
  45. package/server/engine/task/empty-check.ts +38 -0
  46. package/server/engine/task/end.ts +18 -0
  47. package/server/engine/task/floating-point.ts +71 -0
  48. package/server/engine/task/goto.ts +27 -0
  49. package/server/engine/task/graphql-mutate.ts +79 -0
  50. package/server/engine/task/graphql-query.ts +78 -0
  51. package/server/engine/task/headless-post.ts +147 -0
  52. package/server/engine/task/headless-scrap.ts +80 -0
  53. package/server/engine/task/http-get.ts +117 -0
  54. package/server/engine/task/http-post.ts +148 -0
  55. package/server/engine/task/index.ts +45 -0
  56. package/server/engine/task/jsonata.ts +45 -0
  57. package/server/engine/task/local-graphql-mutate.ts +100 -0
  58. package/server/engine/task/local-graphql-query.ts +100 -0
  59. package/server/engine/task/log.ts +78 -0
  60. package/server/engine/task/mqtt-publish.ts +45 -0
  61. package/server/engine/task/mqtt-subscribe.ts +139 -0
  62. package/server/engine/task/mssql-procedure.ts +128 -0
  63. package/server/engine/task/oracle-procedure.ts +124 -0
  64. package/server/engine/task/pick-pending-scenario.ts +80 -0
  65. package/server/engine/task/publish.ts +40 -0
  66. package/server/engine/task/random.ts +53 -0
  67. package/server/engine/task/reset-pending-queue.ts +17 -0
  68. package/server/engine/task/script.ts +63 -0
  69. package/server/engine/task/set-domain.ts +37 -0
  70. package/server/engine/task/sleep.ts +34 -0
  71. package/server/engine/task/socket-listener.ts +96 -0
  72. package/server/engine/task/state-group-read.ts +69 -0
  73. package/server/engine/task/state-read.ts +56 -0
  74. package/server/engine/task/state-write.ts +65 -0
  75. package/server/engine/task/stop-scenario.ts +44 -0
  76. package/server/engine/task/sub-scenario.ts +57 -0
  77. package/server/engine/task/switch-goto.ts +43 -0
  78. package/server/engine/task/switch-range-goto.ts +53 -0
  79. package/server/engine/task/switch-range-scenario.ts +79 -0
  80. package/server/engine/task/switch-range-set.ts +48 -0
  81. package/server/engine/task/switch-scenario.ts +67 -0
  82. package/server/engine/task/switch-set.ts +37 -0
  83. package/server/engine/task/throw.ts +27 -0
  84. package/server/engine/task/utils/headless-pool-for-scenario.ts +71 -0
  85. package/server/engine/task/utils/substitute.ts +44 -0
  86. package/server/engine/task/variables.ts +17 -0
  87. package/server/engine/task-registry.ts +23 -0
  88. package/server/engine/types.ts +114 -0
  89. package/server/index.ts +20 -0
  90. package/server/migrations/index.ts +9 -0
  91. package/server/restful/index.ts +1 -0
  92. package/server/restful/unstable/index.ts +7 -0
  93. package/server/restful/unstable/run-scenario.ts +51 -0
  94. package/server/restful/unstable/scenario-instance.ts +52 -0
  95. package/server/restful/unstable/scenario-instances.ts +80 -0
  96. package/server/restful/unstable/scenario.ts +41 -0
  97. package/server/restful/unstable/scenarios.ts +69 -0
  98. package/server/restful/unstable/start-scenario.ts +33 -0
  99. package/server/restful/unstable/stop-scenario.ts +30 -0
  100. package/server/routers/scenario-schedule-callback-router.ts +69 -0
  101. package/server/routers/scenario-view-router.ts +46 -0
  102. package/server/routes.ts +30 -0
  103. package/server/service/analysis/analysis-query.ts +13 -0
  104. package/server/service/analysis/index.ts +3 -0
  105. package/server/service/connection/connection-mutation.ts +190 -0
  106. package/server/service/connection/connection-query.ts +87 -0
  107. package/server/service/connection/connection-subscription.ts +104 -0
  108. package/server/service/connection/connection-type.ts +288 -0
  109. package/server/service/connection/index.ts +7 -0
  110. package/server/service/connector/connector-query.ts +62 -0
  111. package/server/service/connector/connector-type.ts +29 -0
  112. package/server/service/connector/index.ts +4 -0
  113. package/server/service/index.ts +52 -0
  114. package/server/service/payload-log/index.ts +7 -0
  115. package/server/service/payload-log/payload-log-mutation.ts +151 -0
  116. package/server/service/payload-log/payload-log-query.ts +49 -0
  117. package/server/service/payload-log/payload-log-type.ts +36 -0
  118. package/server/service/payload-log/payload-log.ts +100 -0
  119. package/server/service/property-spec.ts +24 -0
  120. package/server/service/scenario/index.ts +6 -0
  121. package/server/service/scenario/scenario-mutation.ts +396 -0
  122. package/server/service/scenario/scenario-query.ts +109 -0
  123. package/server/service/scenario/scenario-type.ts +78 -0
  124. package/server/service/scenario/scenario.ts +124 -0
  125. package/server/service/scenario-flow/scenario-flow.ts +17 -0
  126. package/server/service/scenario-instance/index.ts +6 -0
  127. package/server/service/scenario-instance/scenario-instance-mutation.ts +44 -0
  128. package/server/service/scenario-instance/scenario-instance-query.ts +42 -0
  129. package/server/service/scenario-instance/scenario-instance-subscription.ts +118 -0
  130. package/server/service/scenario-instance/scenario-instance-type.ts +563 -0
  131. package/server/service/scenario-queue/index.ts +4 -0
  132. package/server/service/scenario-queue/scenario-queue-subscription.ts +55 -0
  133. package/server/service/scenario-queue/scenario-queue-type.ts +27 -0
  134. package/server/service/state-register/data-resolver.ts +56 -0
  135. package/server/service/state-register/index.ts +8 -0
  136. package/server/service/state-register/state-register-mutation.ts +166 -0
  137. package/server/service/state-register/state-register-query.ts +80 -0
  138. package/server/service/state-register/state-register-type.ts +80 -0
  139. package/server/service/state-register/state-register.ts +113 -0
  140. package/server/service/step/index.ts +6 -0
  141. package/server/service/step/step-mutation.ts +52 -0
  142. package/server/service/step/step-query.ts +55 -0
  143. package/server/service/step/step-type.ts +215 -0
  144. package/server/service/task-type/index.ts +4 -0
  145. package/server/service/task-type/task-type-query.ts +95 -0
  146. package/server/service/task-type/task-type-type.ts +29 -0
  147. package/translations/en.json +4 -12
  148. package/translations/ja.json +4 -12
  149. package/translations/ko.json +4 -12
  150. package/translations/ms.json +4 -12
  151. package/translations/zh.json +4 -12
  152. package/dist-server/engine/connector/headless-connector.d.ts +0 -23
  153. package/dist-server/engine/connector/headless-connector.js +0 -357
  154. package/dist-server/engine/connector/headless-connector.js.map +0 -1
  155. package/dist-server/engine/resource-pool/headless-pool.d.ts +0 -1
  156. package/dist-server/engine/resource-pool/headless-pool.js +0 -62
  157. package/dist-server/engine/resource-pool/headless-pool.js.map +0 -1
  158. package/dist-server/engine/resource-pool/index.d.ts +0 -1
  159. package/dist-server/engine/resource-pool/index.js +0 -5
  160. package/dist-server/engine/resource-pool/index.js.map +0 -1
@@ -0,0 +1,139 @@
1
+ import mqtt from 'async-mqtt'
2
+
3
+ import { TaskRegistry } from '../task-registry'
4
+ import { ConnectionManager } from '../connection-manager'
5
+ import { sleep } from '@things-factory/utils'
6
+ import { InputStep } from '../../service/step/step-type'
7
+ import { Context } from '../types'
8
+
9
+ function convertDataFormat(data, format) {
10
+ if (format == 'json') {
11
+ return JSON.parse(data)
12
+ } else {
13
+ return data.toString()
14
+ }
15
+ }
16
+
17
+ async function MqttSubscribe(step: InputStep, context: Context) {
18
+ const {
19
+ connection: connectionName,
20
+ params: { topic, dataFormat },
21
+ name
22
+ } = step
23
+
24
+ const { domain, logger, closures, __mqtt_subscriber } = context
25
+ if (!__mqtt_subscriber) {
26
+ context.__mqtt_subscriber = {}
27
+ }
28
+
29
+ const {
30
+ connection: {
31
+ endpoint: uri,
32
+ params: { user, password }
33
+ }
34
+ } = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
35
+
36
+ if (!topic) {
37
+ throw Error(`topic is not found for ${connectionName}`)
38
+ }
39
+
40
+ /*
41
+ * 1. subscriber list에서 subscriber를 찾는다. 없으면, 생성한다.
42
+ * 2. client.once(...)로 메시지를 취한다.
43
+ *
44
+ * TODO 동일 브로커의 다중 subscribe 태스크에 대해서 완벽한 지원을 해야한다.
45
+ * - 현재는 여러 태스크가 동일 topic을 subscribe 하는 경우에 정상동작하지 않을 것이다.
46
+ */
47
+ if (!context.__mqtt_subscriber[name]) {
48
+ try {
49
+ var broker = null
50
+ if (user && password) {
51
+ broker = await mqtt.connectAsync(uri, { username: user, password: password })
52
+ } else {
53
+ broker = await mqtt.connectAsync(uri)
54
+ }
55
+
56
+ logger.info(`mqtt-connector connection(${connectionName}:${uri}) is connected`)
57
+
58
+ await broker.subscribe(topic)
59
+ logger.info(`success subscribing topic '${topic}'`)
60
+
61
+ var TOPIC
62
+ var MESSAGE
63
+
64
+ context.__mqtt_subscriber[name] = async () => {
65
+ while (!MESSAGE) {
66
+ await sleep(100)
67
+ }
68
+
69
+ var topic = TOPIC
70
+ var message = MESSAGE
71
+
72
+ TOPIC = null
73
+ MESSAGE = null
74
+
75
+ return {
76
+ topic,
77
+ message
78
+ }
79
+ }
80
+
81
+ broker.on('message', async (messageTopic, message) => {
82
+ if (topic !== messageTopic) {
83
+ return
84
+ }
85
+
86
+ TOPIC = topic
87
+ MESSAGE = convertDataFormat(message, dataFormat)
88
+
89
+ // logger.info(`mqtt-subscribe :\n'${message.toString()}'`)
90
+ })
91
+
92
+ closures.push(async () => {
93
+ try {
94
+ broker && (await broker.end())
95
+ logger.info(`mqtt-connector connection(${connectionName}:${uri}) is disconnected`)
96
+ } catch (e) {
97
+ logger.error(e)
98
+ }
99
+ })
100
+ } catch (e) {
101
+ logger.error(e)
102
+ }
103
+ }
104
+
105
+ var { message } = await context.__mqtt_subscriber[name]()
106
+
107
+ return {
108
+ data: message
109
+ }
110
+ }
111
+
112
+ MqttSubscribe.parameterSpec = [
113
+ {
114
+ type: 'string',
115
+ name: 'topic',
116
+ label: 'topic'
117
+ },
118
+ {
119
+ type: 'select',
120
+ label: 'data-format',
121
+ name: 'dataFormat',
122
+ property: {
123
+ options: [
124
+ {
125
+ display: 'Plain Text',
126
+ value: 'text'
127
+ },
128
+ {
129
+ display: 'JSON',
130
+ value: 'json'
131
+ }
132
+ ]
133
+ }
134
+ }
135
+ ]
136
+
137
+ MqttSubscribe.help = 'integration/task/mqtt-subscribe'
138
+
139
+ TaskRegistry.registerTaskHandler('mqtt-subscribe', MqttSubscribe)
@@ -0,0 +1,128 @@
1
+ import { logger } from '@things-factory/env'
2
+ import { access } from '@things-factory/utils'
3
+ import { ConnectionManager } from '../connection-manager'
4
+ import { TaskRegistry } from '../task-registry'
5
+ import { InputStep } from '../../service/step/step-type'
6
+ import { Context } from '../types'
7
+ import 'ses'
8
+
9
+ try {
10
+ var mssql = require('mssql')
11
+ } catch (err) {
12
+ logger.error('mssql module loading failed', err)
13
+ }
14
+
15
+ type ProcedureParameterType = {
16
+ name: string
17
+ dir: string
18
+ type: string
19
+ val?: any
20
+ accessor?: string
21
+ maxSize?: number
22
+ }
23
+
24
+ type ValueType = {
25
+ code?: string
26
+ procedure?: string
27
+ parameters?: ProcedureParameterType[]
28
+ }
29
+
30
+ const DIR = {
31
+ In: 'in',
32
+ Out: 'out',
33
+ Inout: 'inout' /* 초기값이 있는 out 파라미터 */
34
+ }
35
+
36
+ const NUMBER_TYPES = [
37
+ 'TINYINT',
38
+ 'SMALLINT',
39
+ 'INT',
40
+ 'BIGINT',
41
+ 'FLOAT',
42
+ 'READ',
43
+ 'DECIMAL',
44
+ 'NUMERIC',
45
+ 'MONEY',
46
+ 'SMALLMONEY'
47
+ ]
48
+
49
+ const DATE_TYPES = ['DATE', 'TIME', 'DATETIME', 'SMALLDATETIME', 'DATETIME2']
50
+ const PARAMETERIZED_STRINGS = ['NCHAR', 'NVARCHAR', 'NTEXT', 'DECIMAL', 'NUMERIC']
51
+
52
+ async function MssqlProcedure(step: InputStep, context: Context) {
53
+ var { domain, user, data, variables, lng } = context
54
+ var { connection: connectionName, params } = step
55
+
56
+ var { code = '', procedure = '', parameters = [] } = params.parameters as ValueType
57
+
58
+ var dbconnection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
59
+
60
+ if (!code) {
61
+ throw 'procedure code not defined'
62
+ }
63
+
64
+ const compartment = new Compartment({
65
+ domain,
66
+ user,
67
+ lng,
68
+ data,
69
+ variables,
70
+ console
71
+ })
72
+
73
+ let evalCode
74
+ try {
75
+ evalCode = compartment.evaluate('`' + code + '`')
76
+ } catch (err) {
77
+ throw new Error(`Failed to evaluate code: ${err.message}`)
78
+ }
79
+
80
+ code = evalCode
81
+
82
+ const procedureParameters =
83
+ parameters &&
84
+ parameters.reduce((sum, { name, val, dir, type, accessor, maxSize }) => {
85
+ sum[name] = {
86
+ dir: DIR[dir],
87
+ type
88
+ }
89
+
90
+ const calculated = accessor ? access(accessor, data) || val : val
91
+
92
+ if (calculated !== undefined) {
93
+ sum[name].val = NUMBER_TYPES.includes(type)
94
+ ? Number(calculated)
95
+ : DATE_TYPES.includes(type)
96
+ ? new Date(calculated)
97
+ : String(calculated)
98
+ }
99
+
100
+ if ((dir == DIR.In || dir == DIR.Inout) && maxSize > 0 && type == 'String') {
101
+ sum[name].type = mssql?.VarChar(maxSize)
102
+ sum[name].maxSize = maxSize
103
+ }
104
+
105
+ return sum
106
+ }, {})
107
+
108
+ const result = await dbconnection.execute(procedure, procedureParameters)
109
+
110
+ return {
111
+ data: result
112
+ }
113
+ }
114
+
115
+ MssqlProcedure.parameterSpec = [
116
+ {
117
+ type: 'procedure-parameters',
118
+ name: 'parameters',
119
+ label: '',
120
+ property: {
121
+ dbtype: 'mssql'
122
+ }
123
+ }
124
+ ]
125
+
126
+ MssqlProcedure.help = 'integration/task/mssql-procedure'
127
+
128
+ TaskRegistry.registerTaskHandler('mssql-procedure', MssqlProcedure)
@@ -0,0 +1,124 @@
1
+ import { logger } from '@things-factory/env'
2
+ import { access } from '@things-factory/utils'
3
+ import { ConnectionManager } from '../connection-manager'
4
+ import { TaskRegistry } from '../task-registry'
5
+ import { InputStep } from '../../service/step/step-type'
6
+ import { Context } from '../types'
7
+ import 'ses'
8
+
9
+ try {
10
+ var oracledb = require('oracledb')
11
+ } catch (err) {
12
+ logger.error('oracledb module loading failed', err)
13
+ }
14
+
15
+ type ProcedureParameterType = {
16
+ name: string
17
+ dir: string
18
+ type: string
19
+ val?: any
20
+ accessor?: string
21
+ maxSize?: number
22
+ }
23
+
24
+ type ValueType = {
25
+ code?: string
26
+ procedure?: string
27
+ parameters?: ProcedureParameterType[]
28
+ }
29
+
30
+ const TYPES = {
31
+ Number: oracledb?.NUMBER,
32
+ String: oracledb?.STRING,
33
+ Date: oracledb?.DATE,
34
+ Buffer: oracledb?.BUFFER,
35
+ Blob: oracledb?.BLOB,
36
+ Clob: oracledb?.CLOB,
37
+ Cursor: oracledb?.CURSOR
38
+ }
39
+
40
+ const DIR = {
41
+ In: oracledb?.BIND_IN,
42
+ Inout: oracledb?.BIND_INOUT,
43
+ Out: oracledb?.BIND_OUT
44
+ }
45
+
46
+ async function OracleProcedure(step: InputStep, context: Context) {
47
+ var { domain, user, data, variables, lng } = context
48
+ var { connection: connectionName, params } = step
49
+
50
+ var { code = '', parameters = [] } = params.parameters as ValueType
51
+
52
+ var dbconnection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
53
+
54
+ if (!code) {
55
+ throw 'procedure code not defined'
56
+ }
57
+
58
+ const compartment = new Compartment({
59
+ domain,
60
+ user,
61
+ lng,
62
+ data,
63
+ variables,
64
+ console
65
+ })
66
+
67
+ let evalCode
68
+ try {
69
+ evalCode = compartment.evaluate('`' + code + '`')
70
+ } catch (err) {
71
+ throw new Error(`Failed to evaluate code: ${err.message}`)
72
+ }
73
+
74
+ code = evalCode
75
+
76
+ const procedureParameters =
77
+ parameters &&
78
+ parameters.reduce((sum, { name, val, dir, type, accessor, maxSize }) => {
79
+ sum[name] = {
80
+ dir: DIR[dir],
81
+ type: TYPES[type]
82
+ }
83
+
84
+ const calculated = accessor ? access(accessor, data) || val : val
85
+
86
+ if (calculated !== undefined) {
87
+ sum[name].val =
88
+ type === 'Date'
89
+ ? new Date(calculated)
90
+ : type == 'Number'
91
+ ? Number(calculated)
92
+ : type == 'String'
93
+ ? String(calculated)
94
+ : calculated
95
+ }
96
+
97
+ if (maxSize) {
98
+ sum[name].maxSize = maxSize
99
+ }
100
+
101
+ return sum
102
+ }, {})
103
+
104
+ const result = await dbconnection.execute(code, procedureParameters)
105
+
106
+ return {
107
+ data: result
108
+ }
109
+ }
110
+
111
+ OracleProcedure.parameterSpec = [
112
+ {
113
+ type: 'procedure-parameters',
114
+ name: 'parameters',
115
+ label: '',
116
+ property: {
117
+ dbtype: 'oracle'
118
+ }
119
+ }
120
+ ]
121
+
122
+ OracleProcedure.help = 'integration/task/oracle-procedure'
123
+
124
+ TaskRegistry.registerTaskHandler('oracle-procedure', OracleProcedure)
@@ -0,0 +1,80 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+ import { sleep } from '@things-factory/utils'
3
+
4
+ import { Scenario } from '../../service/scenario/scenario'
5
+ import { ScenarioEngine } from '../scenario-engine'
6
+ import { TaskRegistry } from '../task-registry'
7
+ import { InputStep } from '../../service/step/step-type'
8
+ import { Context } from '../types'
9
+
10
+ const debug = require('debug')('things-factory:integration-base:pick-pending-scenario')
11
+
12
+ async function PickPendingScenario(step: InputStep, context: Context) {
13
+ var { logger, load, domain } = context
14
+ var { params } = step
15
+ var { tag = '', waitFor = -1 } = params || {}
16
+
17
+ waitFor = Number(waitFor) || -1
18
+ const till = Date.now() + waitFor
19
+
20
+ const pendingQueue = ScenarioEngine.getPendingQueue(domain)
21
+
22
+ // long-term task need to check state whether this scenario is still going.
23
+ while (true && context.checkState()) {
24
+ var { stuff } = pendingQueue.pick(tag) || {}
25
+ if (stuff) {
26
+ break
27
+ }
28
+
29
+ let toTill = waitFor == -1 ? 1000 : till - Date.now()
30
+ if (toTill <= 0) {
31
+ return {}
32
+ }
33
+
34
+ await sleep(Math.min(1000, toTill))
35
+ }
36
+
37
+ if (!stuff) {
38
+ return
39
+ }
40
+
41
+ var { scenario, variables } = stuff
42
+
43
+ var subscenario = await getRepository(Scenario).findOne({
44
+ where: {
45
+ id: scenario
46
+ },
47
+ relations: ['steps', 'domain']
48
+ })
49
+
50
+ logger.info(`Scenario '${subscenario.name}' Started.`)
51
+ var subContext = await load(step, subscenario, {
52
+ ...context,
53
+ data: {},
54
+ variables
55
+ })
56
+ logger.info(`Scenario '${subscenario.name}' done.`)
57
+
58
+ return {
59
+ data: subContext.data
60
+ }
61
+ }
62
+
63
+ PickPendingScenario.parameterSpec = [
64
+ {
65
+ type: 'string',
66
+ name: 'tag',
67
+ label: 'tag'
68
+ },
69
+ {
70
+ type: 'number',
71
+ name: 'waitFor',
72
+ label: 'wait-for',
73
+ placeHolder: 'milli-seconds'
74
+ }
75
+ ]
76
+
77
+ PickPendingScenario.connectorFree = true
78
+ PickPendingScenario.help = 'integration/task/pick-pending-scenario'
79
+
80
+ TaskRegistry.registerTaskHandler('pick-pending-scenario', PickPendingScenario)
@@ -0,0 +1,40 @@
1
+ import { access } from '@things-factory/utils'
2
+ import { TaskRegistry } from '../task-registry'
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+
6
+ async function Publish(step: InputStep, { logger, publish, data }: Context) {
7
+ var {
8
+ params: { tag, accessor }
9
+ } = step
10
+
11
+ if (!tag || !accessor) {
12
+ throw Error(`tag and accessor should be defined: tag - '${tag}', accessor - '${accessor}'`)
13
+ }
14
+
15
+ var value = access(accessor, data)
16
+
17
+ publish(tag, value)
18
+
19
+ return {
20
+ data: value
21
+ }
22
+ }
23
+
24
+ Publish.parameterSpec = [
25
+ {
26
+ type: 'string',
27
+ name: 'tag',
28
+ label: 'tag'
29
+ },
30
+ {
31
+ type: 'scenario-step-input',
32
+ name: 'accessor',
33
+ label: 'accessor'
34
+ }
35
+ ]
36
+
37
+ Publish.connectorFree = true
38
+ Publish.help = 'integration/task/publish'
39
+
40
+ TaskRegistry.registerTaskHandler('publish', Publish)
@@ -0,0 +1,53 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import Chance from 'chance'
3
+
4
+ import { InputStep } from '../../service/step/step-type'
5
+ import { Context } from '../types'
6
+
7
+ const formats = [
8
+ 'bool,character,floating,integer,letter,natural,string',
9
+ 'paragraph,sentence,syllable,word',
10
+ 'age,birthday,cf,cpf,first,gender,last,name,prefix,ssn,suffix',
11
+ 'android_id,apple_token,bb_pin,wp7_anid,wp8_anid2,avatar,color',
12
+ 'company,domain,email,fbid,google_analytics,hashtag,ip,ipv6,klout,profession,tld,twitter,url',
13
+ 'address,altitude,areacode,city,coordinates,country,depth,geohash,latitude,longitude,phone,postal,province,state,street,zip',
14
+ 'ampm,date,hammertime,hour,millisecond,minute,month,second,timestamp,timezone,weekday,year',
15
+ 'cc,cc_type,currency,currency_pair,dollar,euro,exp,exp_month,exp_year',
16
+ 'coin,d4,d6,d8,d10,d12,d20,d30,d100,guid,hash'
17
+ ]
18
+ .join(',')
19
+ .split(',')
20
+
21
+ async function Random(step: InputStep, { logger, publish, data }: Context) {
22
+ var {
23
+ params: { format = 'integer', count = 1 }
24
+ } = step
25
+
26
+ const chance = new Chance()
27
+
28
+ return {
29
+ data: chance.n(chance[format], count)
30
+ }
31
+ }
32
+
33
+ Random.parameterSpec = [
34
+ {
35
+ type: 'select',
36
+ label: 'format',
37
+ name: 'format',
38
+ property: {
39
+ options: formats.map(format => ({ display: format, value: format }))
40
+ }
41
+ },
42
+ {
43
+ type: 'number',
44
+ label: 'count',
45
+ name: 'count',
46
+ placeholder: '1'
47
+ }
48
+ ]
49
+
50
+ Random.connectorFree = true
51
+ Random.help = 'integration/task/random'
52
+
53
+ TaskRegistry.registerTaskHandler('random', Random)
@@ -0,0 +1,17 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { ScenarioEngine } from '../scenario-engine'
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+
6
+ async function ResetPendingScenario(step: InputStep, { domain }: Context) {
7
+ const pendingQueue = ScenarioEngine.getPendingQueue(domain)
8
+ pendingQueue.reset()
9
+
10
+ return {}
11
+ }
12
+
13
+ ResetPendingScenario.parameterSpec = []
14
+
15
+ ResetPendingScenario.connectorFree = true
16
+
17
+ TaskRegistry.registerTaskHandler('reset-pending-scenario', ResetPendingScenario)
@@ -0,0 +1,63 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { InputStep } from '../../service/step/step-type'
3
+ import { Context } from '../types'
4
+ import 'ses'
5
+
6
+ async function Script(step: InputStep, context: Context) {
7
+ const {
8
+ params: { script }
9
+ } = step
10
+
11
+ const { domain, user, data, variables, lng, logger } = context
12
+
13
+ const compartment = new Compartment({
14
+ domain,
15
+ user,
16
+ data,
17
+ variables,
18
+ logger,
19
+ lng,
20
+ console,
21
+ Math,
22
+ JSON,
23
+ Date,
24
+ setTimeout,
25
+ setInterval,
26
+ clearTimeout,
27
+ clearInterval
28
+ })
29
+
30
+ const scriptSource = `
31
+ (async () => {
32
+ ${script}
33
+ })();
34
+ `
35
+
36
+ try {
37
+ return {
38
+ data: await compartment.evaluate(scriptSource)
39
+ }
40
+ } catch (err) {
41
+ throw new Error(`Script execution failed: ${err.message}`)
42
+ }
43
+ }
44
+
45
+ Script.parameterSpec = [
46
+ {
47
+ type: 'textarea',
48
+ name: 'script',
49
+ label: 'script',
50
+ property: {
51
+ language: 'javascript',
52
+ showLineNumbers: true
53
+ },
54
+ styles: {
55
+ flex: '1'
56
+ }
57
+ }
58
+ ]
59
+
60
+ Script.connectorFree = true
61
+ Script.help = 'integration/task/script'
62
+
63
+ TaskRegistry.registerTaskHandler('script', Script)
@@ -0,0 +1,37 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { Domain, getRepository } from '@things-factory/shell'
3
+
4
+ import { InputStep } from '../../service/step/step-type'
5
+ import { Context } from '../types'
6
+
7
+ async function SetDomain(step: InputStep, context: Context) {
8
+ var {
9
+ params: { subdomain }
10
+ } = step
11
+
12
+ var { logger, domain } = context || {}
13
+
14
+ logger.info(`domain => ${subdomain}`)
15
+
16
+ if (subdomain) {
17
+ context.domain = (await getRepository(Domain).findOneBy({ subdomain })) || domain
18
+ }
19
+
20
+ return {
21
+ data: domain.subdomain // previous domain
22
+ }
23
+ }
24
+
25
+ SetDomain.parameterSpec = [
26
+ {
27
+ type: 'string',
28
+ name: 'subdomain',
29
+ placeholder: 'subdomain',
30
+ label: 'subdomain'
31
+ }
32
+ ]
33
+
34
+ SetDomain.connectorFree = true
35
+ SetDomain.help = 'integration/task/set-domain'
36
+
37
+ TaskRegistry.registerTaskHandler('set-domain', SetDomain)