@things-factory/integration-base 8.0.0-beta.9 → 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,56 @@
1
+ import { ConnectionManager } from '../connection-manager'
2
+ import { TaskRegistry } from '../task-registry'
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+ import 'ses'
6
+
7
+ async function DatabaseQuery(step: InputStep, context: Context) {
8
+ var { domain, user, data, variables, lng } = context
9
+ var {
10
+ connection: connectionName,
11
+ params: { query }
12
+ } = step
13
+
14
+ var dbconnection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
15
+
16
+ const compartment = new Compartment({
17
+ domain,
18
+ user,
19
+ lng,
20
+ data,
21
+ variables,
22
+ console
23
+ })
24
+
25
+ let evalQuery
26
+ try {
27
+ evalQuery = compartment.evaluate('`' + query + '`')
28
+ } catch (err) {
29
+ throw new Error(`Failed to evaluate query: ${err.message}`)
30
+ }
31
+
32
+ var queryResult = await dbconnection.query(evalQuery, [])
33
+
34
+ return {
35
+ data: queryResult
36
+ }
37
+ }
38
+
39
+ DatabaseQuery.parameterSpec = [
40
+ {
41
+ type: 'textarea',
42
+ name: 'query',
43
+ label: 'query',
44
+ property: {
45
+ language: 'sql',
46
+ showLineNumbers: true
47
+ },
48
+ styles: {
49
+ flex: '1'
50
+ }
51
+ }
52
+ ]
53
+
54
+ DatabaseQuery.help = 'integration/task/database-query'
55
+
56
+ TaskRegistry.registerTaskHandler('database-query', DatabaseQuery)
@@ -0,0 +1,21 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { ConnectionManager } from '../connection-manager'
3
+
4
+ import { InputStep } from '../../service/step/step-type'
5
+ import { Context } from '../types'
6
+
7
+ async function EchoReceive(step: InputStep, { logger, domain }: Context) {
8
+ var { connection: connectionName } = step
9
+
10
+ var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
11
+
12
+ var message = await connection.read()
13
+
14
+ return {
15
+ data: message.toString()
16
+ }
17
+ }
18
+
19
+ EchoReceive.parameterSpec = []
20
+
21
+ TaskRegistry.registerTaskHandler('echo-receive', EchoReceive)
@@ -0,0 +1,32 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { ConnectionManager } from '../connection-manager'
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+
6
+ async function EchoSend(step: InputStep, { logger, domain }: Context) {
7
+ var {
8
+ connection: connectionName,
9
+ params: { message }
10
+ } = step
11
+
12
+ var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
13
+ if (!connection) {
14
+ throw Error(`connection is not found : ${connectionName}`)
15
+ }
16
+
17
+ var data = await connection.write(message)
18
+
19
+ return {
20
+ data
21
+ }
22
+ }
23
+
24
+ EchoSend.parameterSpec = [
25
+ {
26
+ type: 'string',
27
+ name: 'message',
28
+ label: 'message'
29
+ }
30
+ ]
31
+
32
+ TaskRegistry.registerTaskHandler('echo-send', EchoSend)
@@ -0,0 +1,38 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { access } from '@things-factory/utils'
3
+
4
+ import { InputStep } from '../../service/step/step-type'
5
+ import { Context } from '../types'
6
+
7
+ async function EmptyCheck(step: InputStep, { logger, data }: Context) {
8
+ var {
9
+ params: { accessor, goto }
10
+ } = step
11
+
12
+ const value = access(accessor, data)
13
+ if ([null, undefined, NaN, ''].indexOf(value) !== -1) {
14
+ return {
15
+ next: goto
16
+ }
17
+ }
18
+
19
+ return {}
20
+ }
21
+
22
+ EmptyCheck.parameterSpec = [
23
+ {
24
+ type: 'scenario-step-input',
25
+ name: 'accessor',
26
+ label: 'accessor'
27
+ },
28
+ {
29
+ type: 'scenario-step-input',
30
+ name: 'goto',
31
+ label: 'goto'
32
+ }
33
+ ]
34
+
35
+ EmptyCheck.connectorFree = true
36
+ EmptyCheck.help = 'integration/task/empty-check'
37
+
38
+ TaskRegistry.registerTaskHandler('empty-check', EmptyCheck)
@@ -0,0 +1,18 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+ import { ScenarioInstanceStatus } from '../../service'
3
+
4
+ import { InputStep } from '../../service/step/step-type'
5
+ import { Context } from '../types'
6
+
7
+ async function End(step: InputStep, { logger }: Context) {
8
+ return {
9
+ state: ScenarioInstanceStatus.STOPPED
10
+ }
11
+ }
12
+
13
+ End.parameterSpec = []
14
+
15
+ End.connectorFree = true
16
+ End.help = 'integration/task/end'
17
+
18
+ TaskRegistry.registerTaskHandler('end', End)
@@ -0,0 +1,71 @@
1
+ import ieee754 from 'ieee754'
2
+ import { access } from '@things-factory/utils'
3
+ import { TaskRegistry } from '../task-registry'
4
+
5
+ import { InputStep } from '../../service/step/step-type'
6
+ import { Context } from '../types'
7
+
8
+ async function FloatingPoint(step: InputStep, { logger, data }: Context) {
9
+ var {
10
+ params: { accessor, operation, endian, floatType }
11
+ } = step
12
+
13
+ const value = access(accessor, data)
14
+ if (typeof value === 'undefined') {
15
+ throw new Error('accessor value not a found')
16
+ }
17
+
18
+ const isLE = endian === 'little'
19
+ const nBytes = floatType === 'float' ? 4 : 8
20
+ const mantissa = floatType === 'float' ? 23 : 52
21
+
22
+ var result
23
+
24
+ if (operation == 'write') {
25
+ result = Buffer.alloc(nBytes)
26
+ ieee754.write(result, value, 0, isLE, mantissa, nBytes)
27
+ } else {
28
+ result = ieee754.read(value, 0, isLE, mantissa, nBytes)
29
+ }
30
+
31
+ return {
32
+ data: result
33
+ }
34
+ }
35
+
36
+ FloatingPoint.parameterSpec = [
37
+ {
38
+ type: 'scenario-step-input',
39
+ name: 'accessor',
40
+ label: 'accessor'
41
+ },
42
+ {
43
+ type: 'select',
44
+ name: 'operation',
45
+ label: 'operation',
46
+ property: {
47
+ options: ['read', 'write']
48
+ }
49
+ },
50
+ {
51
+ type: 'select',
52
+ name: 'endian',
53
+ label: 'endian',
54
+ property: {
55
+ options: ['little', 'big']
56
+ }
57
+ },
58
+ {
59
+ type: 'select',
60
+ name: 'floatType',
61
+ label: 'float type',
62
+ property: {
63
+ options: ['float', 'double']
64
+ }
65
+ }
66
+ ]
67
+
68
+ FloatingPoint.connectorFree = true
69
+ FloatingPoint.help = 'integration/task/floating-point'
70
+
71
+ TaskRegistry.registerTaskHandler('floating-point', FloatingPoint)
@@ -0,0 +1,27 @@
1
+ import { TaskRegistry } from '../task-registry'
2
+
3
+ import { InputStep } from '../../service/step/step-type'
4
+ import { Context } from '../types'
5
+
6
+ async function Goto(step: InputStep, { logger }: Context) {
7
+ var {
8
+ params: { goto }
9
+ } = step
10
+
11
+ return {
12
+ next: goto
13
+ }
14
+ }
15
+
16
+ Goto.parameterSpec = [
17
+ {
18
+ type: 'scenario-step-input',
19
+ name: 'goto',
20
+ label: 'goto'
21
+ }
22
+ ]
23
+
24
+ Goto.connectorFree = true
25
+ Goto.help = 'integration/task/goto'
26
+
27
+ TaskRegistry.registerTaskHandler('goto', Goto)
@@ -0,0 +1,79 @@
1
+ import gql from 'graphql-tag'
2
+ import 'ses'
3
+
4
+ import { access } from '@things-factory/utils'
5
+ import { ConnectionManager } from '../connection-manager'
6
+ import { TaskRegistry } from '../task-registry'
7
+ import { InputStep } from '../../service/step/step-type'
8
+ import { Context } from '../types'
9
+
10
+ async function GraphqlMutate(step: InputStep, context: Context) {
11
+ var { connection: connectionName, params: stepOptions } = step
12
+ var { mutation, variables: variablesAccessorMap, headers } = stepOptions || {}
13
+
14
+ var { domain, user, data, variables, lng } = context
15
+
16
+ const compartment = new Compartment({
17
+ domain,
18
+ user,
19
+ lng,
20
+ data,
21
+ variables,
22
+ console
23
+ })
24
+
25
+ let evalMutation
26
+ try {
27
+ evalMutation = compartment.evaluate('`' + mutation + '`')
28
+ } catch (err) {
29
+ throw new Error(`Failed to evaluate mutation: ${err.message}`)
30
+ }
31
+
32
+ var client = ConnectionManager.getConnectionInstanceByName(context.domain, connectionName)
33
+
34
+ const queryVariables = Object.keys(variablesAccessorMap || {}).reduce((variables, key) => {
35
+ const accessor = variablesAccessorMap[key]
36
+ variables[key] = access(accessor, data)
37
+ return variables
38
+ }, {})
39
+
40
+ var { data: mutateResult } = await client.mutate({
41
+ mutation: gql`
42
+ ${evalMutation}
43
+ `,
44
+ variables: queryVariables,
45
+ headers
46
+ })
47
+
48
+ return {
49
+ data: mutateResult
50
+ }
51
+ }
52
+
53
+ GraphqlMutate.parameterSpec = [
54
+ {
55
+ type: 'graphql',
56
+ name: 'mutation',
57
+ label: 'mutation',
58
+ property: {
59
+ showLineNumbers: true
60
+ },
61
+ styles: {
62
+ flex: 1
63
+ }
64
+ },
65
+ {
66
+ type: 'key-values',
67
+ name: 'variables',
68
+ label: 'variables'
69
+ },
70
+ {
71
+ type: 'key-values',
72
+ name: 'headers',
73
+ label: 'headers'
74
+ }
75
+ ]
76
+
77
+ GraphqlMutate.help = 'integration/task/graphql-mutate'
78
+
79
+ TaskRegistry.registerTaskHandler('graphql-mutate', GraphqlMutate)
@@ -0,0 +1,78 @@
1
+ import gql from 'graphql-tag'
2
+ import 'ses'
3
+
4
+ import { access } from '@things-factory/utils'
5
+ import { ConnectionManager } from '../connection-manager'
6
+ import { TaskRegistry } from '../task-registry'
7
+ import { InputStep } from '../../service/step/step-type'
8
+ import { Context } from '../types'
9
+
10
+ async function GraphqlQuery(step: InputStep, context: Context) {
11
+ var { connection: connectionName, params: stepOptions } = step
12
+ var { query, variables: variablesAccessorMap, headers } = stepOptions || {}
13
+ var { domain, user, data, variables, lng } = context
14
+
15
+ const compartment = new Compartment({
16
+ domain,
17
+ user,
18
+ lng,
19
+ data,
20
+ variables,
21
+ console
22
+ })
23
+
24
+ let evalQuery
25
+ try {
26
+ evalQuery = compartment.evaluate('`' + query + '`')
27
+ } catch (err) {
28
+ throw new Error(`Failed to evaluate query: ${err.message}`)
29
+ }
30
+
31
+ var client = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
32
+
33
+ const queryVariables = Object.keys(variablesAccessorMap || {}).reduce((variables, key) => {
34
+ const accessor = variablesAccessorMap[key]
35
+ variables[key] = access(accessor, data)
36
+ return variables
37
+ }, {})
38
+
39
+ var { data: queryResult } = await client.query({
40
+ query: gql`
41
+ ${evalQuery}
42
+ `,
43
+ variables: queryVariables,
44
+ headers
45
+ })
46
+
47
+ return {
48
+ data: queryResult
49
+ }
50
+ }
51
+
52
+ GraphqlQuery.parameterSpec = [
53
+ {
54
+ type: 'graphql',
55
+ name: 'query',
56
+ label: 'query',
57
+ property: {
58
+ showLineNumbers: true
59
+ },
60
+ styles: {
61
+ flex: 1
62
+ }
63
+ },
64
+ {
65
+ type: 'key-values',
66
+ name: 'variables',
67
+ label: 'variables'
68
+ },
69
+ {
70
+ type: 'key-values',
71
+ name: 'headers',
72
+ label: 'headers'
73
+ }
74
+ ]
75
+
76
+ GraphqlQuery.help = 'integration/task/graphql-query'
77
+
78
+ TaskRegistry.registerTaskHandler('graphql-query', GraphqlQuery)
@@ -0,0 +1,147 @@
1
+ import https from 'https'
2
+ import { URL } from 'url'
3
+
4
+ import { access } from '@things-factory/utils'
5
+ import { TaskRegistry } from '../task-registry'
6
+ import { ConnectionManager } from '../connection-manager'
7
+
8
+ import { getHeadlessPool } from './utils/headless-pool-for-scenario'
9
+
10
+ import { InputStep } from '../../service/step/step-type'
11
+ import { Context } from '../types'
12
+
13
+ async function HeadlessPost(step: InputStep, { logger, data, domain }: Context) {
14
+ var { connection: connectionName, params: stepOptions } = step
15
+ var { headers: requestHeaders, contentType, path, accessor } = stepOptions || {}
16
+
17
+ var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
18
+
19
+ if (!connection) {
20
+ throw new Error(`connection '${connectionName}' is not established.`)
21
+ }
22
+
23
+ var { endpoint, params: connectionParams, authHeaders = {} } = connection
24
+
25
+ var headers = {
26
+ ...authHeaders,
27
+ ...requestHeaders
28
+ }
29
+
30
+ var body = access(accessor, data)
31
+ if (contentType && body) {
32
+ headers['content-type'] = contentType
33
+ switch (contentType) {
34
+ case 'text/plain':
35
+ body = JSON.stringify(body)
36
+ break
37
+ case 'application/json':
38
+ body = JSON.stringify(body)
39
+ break
40
+ case 'application/x-www-form-urlencoded':
41
+ const searchParams = new URLSearchParams()
42
+ for (const prop in body) {
43
+ searchParams.set(prop, body[prop])
44
+ }
45
+ body = searchParams
46
+ break
47
+ }
48
+ }
49
+
50
+ var options: any = {
51
+ method: 'POST',
52
+ headers,
53
+ body
54
+ }
55
+
56
+ var { rejectUnauthorized } = connectionParams
57
+
58
+ if (!rejectUnauthorized) {
59
+ const httpsAgent = new https.Agent({
60
+ rejectUnauthorized
61
+ })
62
+ options.agent = httpsAgent
63
+ }
64
+
65
+ const browser = (await getHeadlessPool().acquire()) as any
66
+ const page = await browser.newPage()
67
+
68
+ try {
69
+ page.on('console', async msg => {
70
+ console.log(`[browser ${msg.type()}] ${msg.text()}`)
71
+ })
72
+
73
+ page.on('requestfailed', request => {
74
+ console.log('Request failed:', request.url())
75
+ })
76
+
77
+ await page.goto(endpoint, { waitUntil: 'networkidle2' })
78
+
79
+ const response = await page.evaluate(
80
+ async (urlString, options) => {
81
+ const response = await fetch(urlString, options)
82
+
83
+ if (response.ok && response.headers.get('content-type').includes('application/json')) {
84
+ return await response.json()
85
+ } else {
86
+ return await response.text()
87
+ }
88
+ },
89
+ new URL(path, endpoint),
90
+ options
91
+ )
92
+
93
+ return {
94
+ data: response
95
+ }
96
+ } catch (e) {
97
+ console.error(e)
98
+ } finally {
99
+ page.close()
100
+ getHeadlessPool().release(browser)
101
+ }
102
+ }
103
+
104
+ HeadlessPost.parameterSpec = [
105
+ {
106
+ type: 'string',
107
+ name: 'path',
108
+ label: 'path'
109
+ },
110
+ {
111
+ type: 'http-headers',
112
+ name: 'headers',
113
+ label: 'headers'
114
+ },
115
+ {
116
+ type: 'select',
117
+ name: 'contentType',
118
+ label: 'content-type',
119
+ property: {
120
+ options: [
121
+ {
122
+ display: '',
123
+ value: ''
124
+ },
125
+ {
126
+ display: 'application/json',
127
+ value: 'application/json'
128
+ },
129
+ {
130
+ display: 'text/plain',
131
+ value: 'text/plain'
132
+ },
133
+ {
134
+ display: 'application/x-www-form-urlencoded',
135
+ value: 'application/x-www-form-urlencoded'
136
+ }
137
+ ]
138
+ }
139
+ },
140
+ {
141
+ type: 'scenario-step-input',
142
+ name: 'accessor',
143
+ label: 'accessor'
144
+ }
145
+ ]
146
+
147
+ TaskRegistry.registerTaskHandler('headless-post', HeadlessPost)
@@ -0,0 +1,80 @@
1
+ import { URL } from 'url'
2
+
3
+ import { TaskRegistry } from '../task-registry'
4
+ import { ConnectionManager } from '../connection-manager'
5
+
6
+ import { getHeadlessPool } from './utils/headless-pool-for-scenario'
7
+ import { InputStep } from '../../service/step/step-type'
8
+ import { Context } from '../types'
9
+
10
+ async function HeadlessScrap(step: InputStep, { logger, data, domain }: Context) {
11
+ var { connection: connectionName, params: stepOptions } = step
12
+ var { headers: requestHeaders, path, selectors = [] } = stepOptions || {}
13
+
14
+ var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)
15
+
16
+ if (!connection) {
17
+ throw new Error(`connection '${connectionName}' is not established.`)
18
+ }
19
+
20
+ var { endpoint, params: connectionParams, authHeaders = {} } = connection
21
+
22
+ var headers = {
23
+ ...authHeaders,
24
+ ...requestHeaders
25
+ }
26
+
27
+ const browser = (await getHeadlessPool().acquire()) as any
28
+ const page = await browser.newPage()
29
+
30
+ try {
31
+ page.on('console', async msg => {
32
+ console.log(`[browser ${msg.type()}] ${msg.text()}`)
33
+ })
34
+
35
+ page.on('requestfailed', request => {
36
+ console.log('Request failed:', request.url())
37
+ })
38
+
39
+ await page.setExtraHTTPHeaders(headers)
40
+ await page.goto(new URL(path, endpoint), { waitUntil: 'networkidle2' })
41
+
42
+ const result = {}
43
+
44
+ for (const selector of selectors) {
45
+ const { text, value } = selector
46
+ result[text] = await page.$$eval(value, elements => {
47
+ return elements.map(element => element.textContent.trim())
48
+ })
49
+ }
50
+
51
+ return {
52
+ data: result
53
+ }
54
+ } catch (e) {
55
+ console.error(e)
56
+ } finally {
57
+ page.close()
58
+ getHeadlessPool().release(browser)
59
+ }
60
+ }
61
+
62
+ HeadlessScrap.parameterSpec = [
63
+ {
64
+ type: 'string',
65
+ name: 'path',
66
+ label: 'path'
67
+ },
68
+ {
69
+ type: 'http-headers',
70
+ name: 'headers',
71
+ label: 'headers'
72
+ },
73
+ {
74
+ type: 'options',
75
+ name: 'selectors',
76
+ label: 'selectors'
77
+ }
78
+ ]
79
+
80
+ TaskRegistry.registerTaskHandler('headless-scrap', HeadlessScrap)