@things-factory/integration-base 8.0.0-beta.9 → 8.0.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/dist-server/engine/connector/http-connector.js +1 -1
- package/dist-server/engine/connector/http-connector.js.map +1 -1
- package/dist-server/engine/connector/index.d.ts +0 -1
- package/dist-server/engine/connector/index.js +0 -1
- package/dist-server/engine/connector/index.js.map +1 -1
- package/dist-server/engine/index.d.ts +0 -1
- package/dist-server/engine/index.js +0 -1
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/task/headless-post.js +33 -19
- package/dist-server/engine/task/headless-post.js.map +1 -1
- package/dist-server/engine/task/headless-scrap.js +13 -20
- package/dist-server/engine/task/headless-scrap.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -12
- package/server/controllers/index.ts +2 -0
- package/server/controllers/publish-data.ts +29 -0
- package/server/controllers/scenario-controller.ts +156 -0
- package/server/engine/analyzer/analyze-integration.ts +115 -0
- package/server/engine/connection-manager.ts +239 -0
- package/server/engine/connector/echo-back-connector.ts +51 -0
- package/server/engine/connector/echo-back-server.ts +72 -0
- package/server/engine/connector/graphql-connector.ts +126 -0
- package/server/engine/connector/http-connector.ts +65 -0
- package/server/engine/connector/index.ts +12 -0
- package/server/engine/connector/mqtt-connector.ts +78 -0
- package/server/engine/connector/mssql-connector.ts +152 -0
- package/server/engine/connector/mysql-connector.ts +94 -0
- package/server/engine/connector/operato-connector.ts +264 -0
- package/server/engine/connector/oracle-connector.ts +218 -0
- package/server/engine/connector/postgresql-connector.ts +152 -0
- package/server/engine/connector/proxy-connector.ts +53 -0
- package/server/engine/connector/socket-server.ts +86 -0
- package/server/engine/connector/sqlite-connector.ts +69 -0
- package/server/engine/edge-client.ts +45 -0
- package/server/engine/index.ts +10 -0
- package/server/engine/pending-queue.ts +97 -0
- package/server/engine/scenario-engine.ts +106 -0
- package/server/engine/task/book-up-scenario.ts +73 -0
- package/server/engine/task/csv-readline.ts +127 -0
- package/server/engine/task/data-accessor.ts +36 -0
- package/server/engine/task/data-mapper.ts +47 -0
- package/server/engine/task/database-query.ts +56 -0
- package/server/engine/task/echo-receive.ts +21 -0
- package/server/engine/task/echo-send.ts +32 -0
- package/server/engine/task/empty-check.ts +38 -0
- package/server/engine/task/end.ts +18 -0
- package/server/engine/task/floating-point.ts +71 -0
- package/server/engine/task/goto.ts +27 -0
- package/server/engine/task/graphql-mutate.ts +79 -0
- package/server/engine/task/graphql-query.ts +78 -0
- package/server/engine/task/headless-post.ts +147 -0
- package/server/engine/task/headless-scrap.ts +80 -0
- package/server/engine/task/http-get.ts +117 -0
- package/server/engine/task/http-post.ts +148 -0
- package/server/engine/task/index.ts +45 -0
- package/server/engine/task/jsonata.ts +45 -0
- package/server/engine/task/local-graphql-mutate.ts +100 -0
- package/server/engine/task/local-graphql-query.ts +100 -0
- package/server/engine/task/log.ts +78 -0
- package/server/engine/task/mqtt-publish.ts +45 -0
- package/server/engine/task/mqtt-subscribe.ts +139 -0
- package/server/engine/task/mssql-procedure.ts +128 -0
- package/server/engine/task/oracle-procedure.ts +124 -0
- package/server/engine/task/pick-pending-scenario.ts +80 -0
- package/server/engine/task/publish.ts +40 -0
- package/server/engine/task/random.ts +53 -0
- package/server/engine/task/reset-pending-queue.ts +17 -0
- package/server/engine/task/script.ts +63 -0
- package/server/engine/task/set-domain.ts +37 -0
- package/server/engine/task/sleep.ts +34 -0
- package/server/engine/task/socket-listener.ts +96 -0
- package/server/engine/task/state-group-read.ts +69 -0
- package/server/engine/task/state-read.ts +56 -0
- package/server/engine/task/state-write.ts +65 -0
- package/server/engine/task/stop-scenario.ts +44 -0
- package/server/engine/task/sub-scenario.ts +57 -0
- package/server/engine/task/switch-goto.ts +43 -0
- package/server/engine/task/switch-range-goto.ts +53 -0
- package/server/engine/task/switch-range-scenario.ts +79 -0
- package/server/engine/task/switch-range-set.ts +48 -0
- package/server/engine/task/switch-scenario.ts +67 -0
- package/server/engine/task/switch-set.ts +37 -0
- package/server/engine/task/throw.ts +27 -0
- package/server/engine/task/utils/headless-pool-for-scenario.ts +71 -0
- package/server/engine/task/utils/substitute.ts +44 -0
- package/server/engine/task/variables.ts +17 -0
- package/server/engine/task-registry.ts +23 -0
- package/server/engine/types.ts +114 -0
- package/server/index.ts +20 -0
- package/server/migrations/index.ts +9 -0
- package/server/restful/index.ts +1 -0
- package/server/restful/unstable/index.ts +7 -0
- package/server/restful/unstable/run-scenario.ts +51 -0
- package/server/restful/unstable/scenario-instance.ts +52 -0
- package/server/restful/unstable/scenario-instances.ts +80 -0
- package/server/restful/unstable/scenario.ts +41 -0
- package/server/restful/unstable/scenarios.ts +69 -0
- package/server/restful/unstable/start-scenario.ts +33 -0
- package/server/restful/unstable/stop-scenario.ts +30 -0
- package/server/routers/scenario-schedule-callback-router.ts +69 -0
- package/server/routers/scenario-view-router.ts +46 -0
- package/server/routes.ts +30 -0
- package/server/service/analysis/analysis-query.ts +13 -0
- package/server/service/analysis/index.ts +3 -0
- package/server/service/connection/connection-mutation.ts +190 -0
- package/server/service/connection/connection-query.ts +87 -0
- package/server/service/connection/connection-subscription.ts +104 -0
- package/server/service/connection/connection-type.ts +288 -0
- package/server/service/connection/index.ts +7 -0
- package/server/service/connector/connector-query.ts +62 -0
- package/server/service/connector/connector-type.ts +29 -0
- package/server/service/connector/index.ts +4 -0
- package/server/service/index.ts +52 -0
- package/server/service/payload-log/index.ts +7 -0
- package/server/service/payload-log/payload-log-mutation.ts +151 -0
- package/server/service/payload-log/payload-log-query.ts +49 -0
- package/server/service/payload-log/payload-log-type.ts +36 -0
- package/server/service/payload-log/payload-log.ts +100 -0
- package/server/service/property-spec.ts +24 -0
- package/server/service/scenario/index.ts +6 -0
- package/server/service/scenario/scenario-mutation.ts +396 -0
- package/server/service/scenario/scenario-query.ts +109 -0
- package/server/service/scenario/scenario-type.ts +78 -0
- package/server/service/scenario/scenario.ts +124 -0
- package/server/service/scenario-flow/scenario-flow.ts +17 -0
- package/server/service/scenario-instance/index.ts +6 -0
- package/server/service/scenario-instance/scenario-instance-mutation.ts +44 -0
- package/server/service/scenario-instance/scenario-instance-query.ts +42 -0
- package/server/service/scenario-instance/scenario-instance-subscription.ts +118 -0
- package/server/service/scenario-instance/scenario-instance-type.ts +563 -0
- package/server/service/scenario-queue/index.ts +4 -0
- package/server/service/scenario-queue/scenario-queue-subscription.ts +55 -0
- package/server/service/scenario-queue/scenario-queue-type.ts +27 -0
- package/server/service/state-register/data-resolver.ts +56 -0
- package/server/service/state-register/index.ts +8 -0
- package/server/service/state-register/state-register-mutation.ts +166 -0
- package/server/service/state-register/state-register-query.ts +80 -0
- package/server/service/state-register/state-register-type.ts +80 -0
- package/server/service/state-register/state-register.ts +113 -0
- package/server/service/step/index.ts +6 -0
- package/server/service/step/step-mutation.ts +52 -0
- package/server/service/step/step-query.ts +55 -0
- package/server/service/step/step-type.ts +215 -0
- package/server/service/task-type/index.ts +4 -0
- package/server/service/task-type/task-type-query.ts +95 -0
- package/server/service/task-type/task-type-type.ts +29 -0
- package/translations/en.json +4 -12
- package/translations/ja.json +4 -12
- package/translations/ko.json +4 -12
- package/translations/ms.json +4 -12
- package/translations/zh.json +4 -12
- package/dist-server/engine/connector/headless-connector.d.ts +0 -23
- package/dist-server/engine/connector/headless-connector.js +0 -357
- package/dist-server/engine/connector/headless-connector.js.map +0 -1
- package/dist-server/engine/resource-pool/headless-pool.d.ts +0 -1
- package/dist-server/engine/resource-pool/headless-pool.js +0 -62
- package/dist-server/engine/resource-pool/headless-pool.js.map +0 -1
- package/dist-server/engine/resource-pool/index.d.ts +0 -1
- package/dist-server/engine/resource-pool/index.js +0 -5
- 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)
|