@things-factory/integration-base 8.0.40 → 9.0.0-9.0.0-beta.59.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.
- package/dist-server/engine/connector/headless-connector.d.ts +23 -0
- package/dist-server/engine/connector/headless-connector.js +357 -0
- package/dist-server/engine/connector/headless-connector.js.map +1 -0
- 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 +1 -0
- package/dist-server/engine/connector/index.js +1 -0
- package/dist-server/engine/connector/index.js.map +1 -1
- package/dist-server/engine/index.d.ts +3 -2
- package/dist-server/engine/index.js +3 -2
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/resource-pool/headless-pool.d.ts +1 -0
- package/dist-server/engine/resource-pool/headless-pool.js +62 -0
- package/dist-server/engine/resource-pool/headless-pool.js.map +1 -0
- package/dist-server/engine/resource-pool/index.d.ts +1 -0
- package/dist-server/engine/resource-pool/index.js +5 -0
- package/dist-server/engine/resource-pool/index.js.map +1 -0
- package/dist-server/engine/task/headless-post.js +19 -33
- package/dist-server/engine/task/headless-post.js.map +1 -1
- package/dist-server/engine/task/headless-scrap.js +20 -13
- package/dist-server/engine/task/headless-scrap.js.map +1 -1
- package/dist-server/index.d.ts +6 -6
- package/dist-server/index.js +10 -10
- package/dist-server/index.js.map +1 -1
- package/dist-server/routes.js +6 -6
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/connection/connection-mutation.js +17 -5
- package/dist-server/service/connection/connection-mutation.js.map +1 -1
- package/dist-server/service/connection/connection-query.js +3 -0
- package/dist-server/service/connection/connection-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -11
- package/translations/en.json +12 -4
- package/translations/ja.json +12 -4
- package/translations/ko.json +12 -4
- package/translations/ms.json +12 -4
- package/translations/zh.json +12 -4
- package/server/controllers/index.ts +0 -2
- package/server/controllers/publish-data.ts +0 -29
- package/server/controllers/scenario-controller.ts +0 -154
- package/server/engine/analyzer/analyze-integration.ts +0 -115
- package/server/engine/connection-manager.ts +0 -232
- package/server/engine/connector/echo-back-connector.ts +0 -51
- package/server/engine/connector/echo-back-server.ts +0 -72
- package/server/engine/connector/graphql-connector.ts +0 -126
- package/server/engine/connector/http-connector.ts +0 -65
- package/server/engine/connector/index.ts +0 -12
- package/server/engine/connector/mqtt-connector.ts +0 -78
- package/server/engine/connector/mssql-connector.ts +0 -152
- package/server/engine/connector/mysql-connector.ts +0 -94
- package/server/engine/connector/operato-connector.ts +0 -264
- package/server/engine/connector/oracle-connector.ts +0 -218
- package/server/engine/connector/postgresql-connector.ts +0 -152
- package/server/engine/connector/proxy-connector.ts +0 -53
- package/server/engine/connector/socket-server.ts +0 -86
- package/server/engine/connector/sqlite-connector.ts +0 -69
- package/server/engine/edge-client.ts +0 -45
- package/server/engine/index.ts +0 -10
- package/server/engine/pending-queue.ts +0 -97
- package/server/engine/scenario-engine.ts +0 -106
- package/server/engine/task/book-up-scenario.ts +0 -73
- package/server/engine/task/csv-readline.ts +0 -127
- package/server/engine/task/data-accessor.ts +0 -36
- package/server/engine/task/data-mapper.ts +0 -47
- package/server/engine/task/database-query.ts +0 -56
- package/server/engine/task/echo-receive.ts +0 -21
- package/server/engine/task/echo-send.ts +0 -32
- package/server/engine/task/empty-check.ts +0 -38
- package/server/engine/task/end.ts +0 -18
- package/server/engine/task/floating-point.ts +0 -71
- package/server/engine/task/goto.ts +0 -27
- package/server/engine/task/graphql-mutate.ts +0 -79
- package/server/engine/task/graphql-query.ts +0 -78
- package/server/engine/task/headless-post.ts +0 -147
- package/server/engine/task/headless-scrap.ts +0 -80
- package/server/engine/task/http-get.ts +0 -117
- package/server/engine/task/http-post.ts +0 -148
- package/server/engine/task/index.ts +0 -45
- package/server/engine/task/jsonata.ts +0 -45
- package/server/engine/task/local-graphql-mutate.ts +0 -100
- package/server/engine/task/local-graphql-query.ts +0 -100
- package/server/engine/task/log.ts +0 -78
- package/server/engine/task/mqtt-publish.ts +0 -69
- package/server/engine/task/mqtt-subscribe.ts +0 -291
- package/server/engine/task/mssql-procedure.ts +0 -128
- package/server/engine/task/oracle-procedure.ts +0 -124
- package/server/engine/task/pick-pending-scenario.ts +0 -80
- package/server/engine/task/publish.ts +0 -40
- package/server/engine/task/random.ts +0 -53
- package/server/engine/task/reset-pending-queue.ts +0 -17
- package/server/engine/task/script.ts +0 -63
- package/server/engine/task/set-domain.ts +0 -37
- package/server/engine/task/sleep.ts +0 -34
- package/server/engine/task/socket-listener.ts +0 -96
- package/server/engine/task/state-group-read.ts +0 -69
- package/server/engine/task/state-read.ts +0 -56
- package/server/engine/task/state-write.ts +0 -65
- package/server/engine/task/stop-scenario.ts +0 -44
- package/server/engine/task/sub-scenario.ts +0 -57
- package/server/engine/task/switch-goto.ts +0 -43
- package/server/engine/task/switch-range-goto.ts +0 -53
- package/server/engine/task/switch-range-scenario.ts +0 -79
- package/server/engine/task/switch-range-set.ts +0 -48
- package/server/engine/task/switch-scenario.ts +0 -67
- package/server/engine/task/switch-set.ts +0 -37
- package/server/engine/task/throw.ts +0 -27
- package/server/engine/task/utils/headless-pool-for-scenario.ts +0 -71
- package/server/engine/task/utils/substitute.ts +0 -44
- package/server/engine/task/variables.ts +0 -17
- package/server/engine/task-registry.ts +0 -23
- package/server/engine/types.ts +0 -114
- package/server/index.ts +0 -20
- package/server/migrations/index.ts +0 -9
- package/server/restful/index.ts +0 -1
- package/server/restful/unstable/index.ts +0 -7
- package/server/restful/unstable/run-scenario.ts +0 -51
- package/server/restful/unstable/scenario-instance.ts +0 -52
- package/server/restful/unstable/scenario-instances.ts +0 -80
- package/server/restful/unstable/scenario.ts +0 -41
- package/server/restful/unstable/scenarios.ts +0 -69
- package/server/restful/unstable/start-scenario.ts +0 -33
- package/server/restful/unstable/stop-scenario.ts +0 -30
- package/server/routers/scenario-schedule-callback-router.ts +0 -69
- package/server/routers/scenario-view-router.ts +0 -46
- package/server/routes.ts +0 -35
- package/server/service/analysis/analysis-query.ts +0 -13
- package/server/service/analysis/index.ts +0 -3
- package/server/service/connection/connection-mutation.ts +0 -190
- package/server/service/connection/connection-query.ts +0 -87
- package/server/service/connection/connection-subscription.ts +0 -104
- package/server/service/connection/connection-type.ts +0 -305
- package/server/service/connection/index.ts +0 -7
- package/server/service/connector/connector-query.ts +0 -62
- package/server/service/connector/connector-type.ts +0 -29
- package/server/service/connector/index.ts +0 -4
- package/server/service/index.ts +0 -52
- package/server/service/payload-log/index.ts +0 -7
- package/server/service/payload-log/payload-log-mutation.ts +0 -151
- package/server/service/payload-log/payload-log-query.ts +0 -49
- package/server/service/payload-log/payload-log-type.ts +0 -36
- package/server/service/payload-log/payload-log.ts +0 -100
- package/server/service/property-spec.ts +0 -24
- package/server/service/scenario/index.ts +0 -6
- package/server/service/scenario/scenario-mutation.ts +0 -396
- package/server/service/scenario/scenario-query.ts +0 -109
- package/server/service/scenario/scenario-type.ts +0 -78
- package/server/service/scenario/scenario.ts +0 -124
- package/server/service/scenario-flow/scenario-flow.ts +0 -17
- package/server/service/scenario-instance/index.ts +0 -6
- package/server/service/scenario-instance/scenario-instance-mutation.ts +0 -44
- package/server/service/scenario-instance/scenario-instance-query.ts +0 -42
- package/server/service/scenario-instance/scenario-instance-subscription.ts +0 -118
- package/server/service/scenario-instance/scenario-instance-type.ts +0 -557
- package/server/service/scenario-queue/index.ts +0 -4
- package/server/service/scenario-queue/scenario-queue-subscription.ts +0 -55
- package/server/service/scenario-queue/scenario-queue-type.ts +0 -27
- package/server/service/state-register/data-resolver.ts +0 -56
- package/server/service/state-register/index.ts +0 -8
- package/server/service/state-register/state-register-mutation.ts +0 -166
- package/server/service/state-register/state-register-query.ts +0 -80
- package/server/service/state-register/state-register-type.ts +0 -80
- package/server/service/state-register/state-register.ts +0 -113
- package/server/service/step/index.ts +0 -6
- package/server/service/step/step-mutation.ts +0 -52
- package/server/service/step/step-query.ts +0 -55
- package/server/service/step/step-type.ts +0 -238
- package/server/service/task-type/index.ts +0 -4
- package/server/service/task-type/task-type-query.ts +0 -95
- package/server/service/task-type/task-type-type.ts +0 -29
@@ -1,291 +0,0 @@
|
|
1
|
-
import mqtt from 'async-mqtt'
|
2
|
-
|
3
|
-
import { TaskRegistry } from '../task-registry.js'
|
4
|
-
import { ConnectionManager } from '../connection-manager.js'
|
5
|
-
import { InputStep } from '../../service/step/step-type.js'
|
6
|
-
import { Context } from '../types.js'
|
7
|
-
|
8
|
-
function convertDataFormat(data, format) {
|
9
|
-
if (format == 'json') {
|
10
|
-
try {
|
11
|
-
return JSON.parse(data)
|
12
|
-
} catch (e) {
|
13
|
-
console.error('JSON 파싱 오류:', e.message)
|
14
|
-
return data.toString()
|
15
|
-
}
|
16
|
-
} else {
|
17
|
-
return data.toString()
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
// MQTT 연결을 위한 브로커 관리 클래스
|
22
|
-
class MqttBrokerManager {
|
23
|
-
private static brokers: Record<
|
24
|
-
string,
|
25
|
-
{
|
26
|
-
client: mqtt.AsyncMqttClient
|
27
|
-
topics: Set<string>
|
28
|
-
messageHandlers: Map<string, (topic: string, message: Buffer) => void>
|
29
|
-
}
|
30
|
-
> = {}
|
31
|
-
|
32
|
-
// 브로커 연결 (또는 기존 연결 반환)
|
33
|
-
static async getBroker(uri: string, options?: mqtt.IClientOptions) {
|
34
|
-
const brokerKey = `${uri}_${JSON.stringify(options || {})}`
|
35
|
-
|
36
|
-
if (!this.brokers[brokerKey]) {
|
37
|
-
const client = await mqtt.connectAsync(uri, options)
|
38
|
-
|
39
|
-
this.brokers[brokerKey] = {
|
40
|
-
client,
|
41
|
-
topics: new Set<string>(),
|
42
|
-
messageHandlers: new Map()
|
43
|
-
}
|
44
|
-
|
45
|
-
// 메시지 수신 핸들러
|
46
|
-
client.on('message', (topic, message) => {
|
47
|
-
// 해당 토픽에 등록된 핸들러가 있으면 호출
|
48
|
-
this.brokers[brokerKey].messageHandlers.forEach((handler, handlerId) => {
|
49
|
-
if (handlerId.startsWith(`${topic}:`)) {
|
50
|
-
handler(topic, message)
|
51
|
-
}
|
52
|
-
})
|
53
|
-
})
|
54
|
-
}
|
55
|
-
|
56
|
-
return this.brokers[brokerKey]
|
57
|
-
}
|
58
|
-
|
59
|
-
// 토픽 구독 등록
|
60
|
-
static async subscribe(brokerKey: string, topic: string) {
|
61
|
-
const broker = this.brokers[brokerKey]
|
62
|
-
if (!broker) {
|
63
|
-
throw new Error(`브로커가 연결되지 않음: ${brokerKey}`)
|
64
|
-
}
|
65
|
-
|
66
|
-
// 새 토픽인 경우 구독
|
67
|
-
if (!broker.topics.has(topic)) {
|
68
|
-
await broker.client.subscribe(topic)
|
69
|
-
broker.topics.add(topic)
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
// 메시지 핸들러 등록
|
74
|
-
static registerMessageHandler(
|
75
|
-
brokerKey: string,
|
76
|
-
topic: string,
|
77
|
-
handlerId: string,
|
78
|
-
handler: (topic: string, message: Buffer) => void
|
79
|
-
) {
|
80
|
-
const broker = this.brokers[brokerKey]
|
81
|
-
if (!broker) {
|
82
|
-
throw new Error(`브로커가 연결되지 않음: ${brokerKey}`)
|
83
|
-
}
|
84
|
-
|
85
|
-
// 핸들러 ID는 topic:handlerId 형식으로 저장
|
86
|
-
const fullHandlerId = `${topic}:${handlerId}`
|
87
|
-
broker.messageHandlers.set(fullHandlerId, handler)
|
88
|
-
|
89
|
-
return () => {
|
90
|
-
// 핸들러 제거 함수 반환
|
91
|
-
broker.messageHandlers.delete(fullHandlerId)
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
// 연결 종료
|
96
|
-
static async disconnect(brokerKey: string) {
|
97
|
-
const broker = this.brokers[brokerKey]
|
98
|
-
if (broker) {
|
99
|
-
await broker.client.end()
|
100
|
-
delete this.brokers[brokerKey]
|
101
|
-
}
|
102
|
-
}
|
103
|
-
|
104
|
-
// 브로커 키 생성 유틸리티
|
105
|
-
static getBrokerKey(uri: string, options?: any) {
|
106
|
-
return `${uri}_${JSON.stringify(options || {})}`
|
107
|
-
}
|
108
|
-
}
|
109
|
-
|
110
|
-
interface MqttContext extends Context {
|
111
|
-
__mqtt_connections?: Set<string>
|
112
|
-
__mqtt_handlers?: Map<string, () => void>
|
113
|
-
__mqtt_resolvers?: Map<string, (result: any) => void>
|
114
|
-
}
|
115
|
-
|
116
|
-
async function MqttSubscribe(step: InputStep, context: MqttContext) {
|
117
|
-
const {
|
118
|
-
connection: connectionName,
|
119
|
-
params: { topic, dataFormat },
|
120
|
-
name: stepName
|
121
|
-
} = step
|
122
|
-
|
123
|
-
const { domain, logger, closures } = context
|
124
|
-
|
125
|
-
// MQTT 브로커 접속 정보 가져오기
|
126
|
-
const {
|
127
|
-
connection: {
|
128
|
-
endpoint: uri,
|
129
|
-
params: { user, password }
|
130
|
-
}
|
131
|
-
} = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
|
132
|
-
|
133
|
-
if (!topic) {
|
134
|
-
throw Error(`토픽이 지정되지 않음: ${connectionName}`)
|
135
|
-
}
|
136
|
-
|
137
|
-
// 브로커 연결 키 생성
|
138
|
-
const connectionOptions = user && password ? { username: user, password } : undefined
|
139
|
-
const brokerKey = MqttBrokerManager.getBrokerKey(uri, connectionOptions)
|
140
|
-
|
141
|
-
// 구독자 ID 생성 (도메인, 연결명, 토픽, 스텝명 조합)
|
142
|
-
const subscriberId = `${domain}_${connectionName}_${topic}_${stepName}`
|
143
|
-
|
144
|
-
try {
|
145
|
-
// 브로커 연결 (또는 기존 연결 가져오기)
|
146
|
-
await MqttBrokerManager.getBroker(uri, connectionOptions)
|
147
|
-
logger.info(`MQTT 연결 완료: ${connectionName}:${uri}`)
|
148
|
-
|
149
|
-
// 토픽 구독 등록
|
150
|
-
await MqttBrokerManager.subscribe(brokerKey, topic)
|
151
|
-
logger.info(`토픽 구독 완료: ${topic}`)
|
152
|
-
|
153
|
-
// 리졸버 저장소 초기화
|
154
|
-
if (!context.__mqtt_resolvers) {
|
155
|
-
context.__mqtt_resolvers = new Map()
|
156
|
-
}
|
157
|
-
|
158
|
-
// 클로저에 연결 종료 함수 등록
|
159
|
-
if (!context.__mqtt_connections) {
|
160
|
-
context.__mqtt_connections = new Set()
|
161
|
-
}
|
162
|
-
|
163
|
-
if (!context.__mqtt_handlers) {
|
164
|
-
context.__mqtt_handlers = new Map()
|
165
|
-
}
|
166
|
-
|
167
|
-
// 연결 추적 (중복 종료 방지)
|
168
|
-
if (!context.__mqtt_connections.has(brokerKey)) {
|
169
|
-
context.__mqtt_connections.add(brokerKey)
|
170
|
-
|
171
|
-
// 연결 종료 함수 등록
|
172
|
-
closures.push(async () => {
|
173
|
-
try {
|
174
|
-
// 핸들러 모두 제거
|
175
|
-
if (context.__mqtt_handlers) {
|
176
|
-
context.__mqtt_handlers.forEach(removeHandler => {
|
177
|
-
removeHandler()
|
178
|
-
})
|
179
|
-
context.__mqtt_handlers.clear()
|
180
|
-
}
|
181
|
-
|
182
|
-
// 대기 중인 모든 Promise 해결
|
183
|
-
if (context.__mqtt_resolvers) {
|
184
|
-
context.__mqtt_resolvers.forEach(resolver => {
|
185
|
-
resolver({ data: null, terminated: true })
|
186
|
-
})
|
187
|
-
context.__mqtt_resolvers.clear()
|
188
|
-
}
|
189
|
-
|
190
|
-
// 연결 종료
|
191
|
-
await MqttBrokerManager.disconnect(brokerKey)
|
192
|
-
logger.info(`MQTT 연결 종료: ${connectionName}:${uri}`)
|
193
|
-
} catch (e) {
|
194
|
-
logger.error(`MQTT 연결 종료 오류: ${e.message}`)
|
195
|
-
}
|
196
|
-
})
|
197
|
-
}
|
198
|
-
|
199
|
-
// Promise로 메시지 수신 대기
|
200
|
-
return new Promise(resolve => {
|
201
|
-
// 이 태스크의 resolver 저장
|
202
|
-
if (context.__mqtt_resolvers) {
|
203
|
-
context.__mqtt_resolvers.set(subscriberId, resolve)
|
204
|
-
}
|
205
|
-
|
206
|
-
// 이미 등록된 핸들러가 있으면 제거
|
207
|
-
if (context.__mqtt_handlers?.has(subscriberId)) {
|
208
|
-
const removeHandler = context.__mqtt_handlers.get(subscriberId)
|
209
|
-
if (removeHandler) {
|
210
|
-
removeHandler()
|
211
|
-
}
|
212
|
-
}
|
213
|
-
|
214
|
-
// 새로운 메시지 핸들러 등록
|
215
|
-
const removeHandler = MqttBrokerManager.registerMessageHandler(
|
216
|
-
brokerKey,
|
217
|
-
topic,
|
218
|
-
subscriberId,
|
219
|
-
(messageTopic, message) => {
|
220
|
-
try {
|
221
|
-
// 메시지 변환
|
222
|
-
const convertedMessage = convertDataFormat(message, dataFormat)
|
223
|
-
|
224
|
-
// resolver 가져오기 및 삭제
|
225
|
-
if (context.__mqtt_resolvers?.has(subscriberId)) {
|
226
|
-
const resolver = context.__mqtt_resolvers.get(subscriberId)
|
227
|
-
context.__mqtt_resolvers.delete(subscriberId)
|
228
|
-
|
229
|
-
// 이 태스크에 대한 핸들러 제거 (한 번만 실행되도록)
|
230
|
-
if (context.__mqtt_handlers?.has(subscriberId)) {
|
231
|
-
const removeHandler = context.__mqtt_handlers.get(subscriberId)
|
232
|
-
if (removeHandler) {
|
233
|
-
removeHandler()
|
234
|
-
}
|
235
|
-
context.__mqtt_handlers.delete(subscriberId)
|
236
|
-
}
|
237
|
-
|
238
|
-
// Promise 해결
|
239
|
-
if (resolver) {
|
240
|
-
resolver({
|
241
|
-
data: convertedMessage
|
242
|
-
})
|
243
|
-
}
|
244
|
-
}
|
245
|
-
} catch (error) {
|
246
|
-
logger.error(`메시지 처리 오류: ${error.message}`)
|
247
|
-
}
|
248
|
-
}
|
249
|
-
)
|
250
|
-
|
251
|
-
// 핸들러 제거 함수 저장
|
252
|
-
if (context.__mqtt_handlers) {
|
253
|
-
context.__mqtt_handlers.set(subscriberId, removeHandler)
|
254
|
-
}
|
255
|
-
|
256
|
-
logger.info(`MQTT 메시지 대기 중: ${topic}`)
|
257
|
-
})
|
258
|
-
} catch (e) {
|
259
|
-
logger.error(`MQTT 구독 오류: ${e.message}`)
|
260
|
-
throw e
|
261
|
-
}
|
262
|
-
}
|
263
|
-
|
264
|
-
MqttSubscribe.parameterSpec = [
|
265
|
-
{
|
266
|
-
type: 'string',
|
267
|
-
name: 'topic',
|
268
|
-
label: 'topic'
|
269
|
-
},
|
270
|
-
{
|
271
|
-
type: 'select',
|
272
|
-
label: 'data-format',
|
273
|
-
name: 'dataFormat',
|
274
|
-
property: {
|
275
|
-
options: [
|
276
|
-
{
|
277
|
-
display: 'Plain Text',
|
278
|
-
value: 'text'
|
279
|
-
},
|
280
|
-
{
|
281
|
-
display: 'JSON',
|
282
|
-
value: 'json'
|
283
|
-
}
|
284
|
-
]
|
285
|
-
}
|
286
|
-
}
|
287
|
-
]
|
288
|
-
|
289
|
-
MqttSubscribe.help = 'integration/task/mqtt-subscribe'
|
290
|
-
|
291
|
-
TaskRegistry.registerTaskHandler('mqtt-subscribe', MqttSubscribe)
|
@@ -1,128 +0,0 @@
|
|
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)
|
@@ -1,124 +0,0 @@
|
|
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)
|
@@ -1,80 +0,0 @@
|
|
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)
|
@@ -1,40 +0,0 @@
|
|
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)
|
@@ -1,53 +0,0 @@
|
|
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)
|