@logicflow/engine 0.0.10-beta.0 → 0.0.11-beta.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 (189) hide show
  1. package/README.md +2 -5
  2. package/cjs/EventEmitter.js +70 -0
  3. package/cjs/FlowModel.js +277 -0
  4. package/cjs/Scheduler.js +252 -0
  5. package/{lib/constant/logCode.js → cjs/constant/LogCode.js} +13 -16
  6. package/{lib/constant/index.js → cjs/constant/constant.js} +3 -4
  7. package/cjs/expression/browserVm.js +81 -0
  8. package/cjs/expression/index.js +57 -0
  9. package/cjs/index.js +210 -0
  10. package/cjs/nodes/BaseNode.js +252 -0
  11. package/cjs/nodes/StartNode.js +27 -0
  12. package/cjs/nodes/TaskNode.js +27 -0
  13. package/cjs/recorder/index.js +168 -0
  14. package/cjs/util/ID.js +16 -0
  15. package/cjs/util/global.js +32 -0
  16. package/{lib/utils → cjs/util}/storage.js +17 -18
  17. package/es/EventEmitter.d.ts +4 -34
  18. package/es/EventEmitter.js +48 -70
  19. package/es/FlowModel.d.ts +73 -75
  20. package/es/FlowModel.js +173 -130
  21. package/es/Scheduler.d.ts +34 -50
  22. package/es/Scheduler.js +209 -134
  23. package/es/constant/LogCode.js +28 -0
  24. package/es/constant/{index.js → constant.js} +7 -8
  25. package/es/expression/browserVm.d.ts +4 -0
  26. package/es/expression/browserVm.js +76 -0
  27. package/es/expression/index.d.ts +1 -1
  28. package/es/expression/index.js +53 -16
  29. package/es/index.d.ts +38 -135
  30. package/es/index.js +144 -92
  31. package/es/nodes/BaseNode.d.ts +110 -0
  32. package/es/nodes/BaseNode.js +250 -0
  33. package/es/nodes/{start.d.ts → StartNode.d.ts} +2 -3
  34. package/es/nodes/StartNode.js +25 -0
  35. package/es/nodes/{task.d.ts → TaskNode.d.ts} +2 -3
  36. package/es/nodes/TaskNode.js +25 -0
  37. package/es/recorder/index.d.ts +10 -36
  38. package/es/recorder/index.js +135 -82
  39. package/es/util/ID.js +13 -0
  40. package/es/util/global.d.ts +5 -0
  41. package/es/util/global.js +26 -0
  42. package/es/{utils → util}/storage.js +16 -17
  43. package/lib/main.js +1 -0
  44. package/package.json +71 -30
  45. package/dist/index.js +0 -2
  46. package/dist/index.js.map +0 -1
  47. package/es/EventEmitter.js.map +0 -1
  48. package/es/FlowModel.js.map +0 -1
  49. package/es/Scheduler.js.map +0 -1
  50. package/es/constant/index.js.map +0 -1
  51. package/es/constant/logCode.js +0 -29
  52. package/es/constant/logCode.js.map +0 -1
  53. package/es/expression/brewserVm.d.ts +0 -2
  54. package/es/expression/brewserVm.js +0 -30
  55. package/es/expression/brewserVm.js.map +0 -1
  56. package/es/expression/index.js.map +0 -1
  57. package/es/expression/nodeVm.d.ts +0 -4
  58. package/es/expression/nodeVm.js +0 -10
  59. package/es/expression/nodeVm.js.map +0 -1
  60. package/es/index.js.map +0 -1
  61. package/es/nodes/base.d.ts +0 -108
  62. package/es/nodes/base.js +0 -149
  63. package/es/nodes/base.js.map +0 -1
  64. package/es/nodes/index.d.ts +0 -3
  65. package/es/nodes/index.js +0 -4
  66. package/es/nodes/index.js.map +0 -1
  67. package/es/nodes/start.js +0 -11
  68. package/es/nodes/start.js.map +0 -1
  69. package/es/nodes/task.js +0 -11
  70. package/es/nodes/task.js.map +0 -1
  71. package/es/platform/browser/browserVm.d.ts +0 -4
  72. package/es/platform/browser/browserVm.js +0 -44
  73. package/es/platform/browser/browserVm.js.map +0 -1
  74. package/es/platform/browser/index.d.ts +0 -4
  75. package/es/platform/browser/index.js +0 -23
  76. package/es/platform/browser/index.js.map +0 -1
  77. package/es/platform/index.d.ts +0 -1
  78. package/es/platform/index.js +0 -2
  79. package/es/platform/index.js.map +0 -1
  80. package/es/platform/node/index.d.ts +0 -4
  81. package/es/platform/node/index.js +0 -23
  82. package/es/platform/node/index.js.map +0 -1
  83. package/es/platform/node/nodeVm.d.ts +0 -1
  84. package/es/platform/node/nodeVm.js +0 -9
  85. package/es/platform/node/nodeVm.js.map +0 -1
  86. package/es/recorder/index.js.map +0 -1
  87. package/es/utils/global.d.ts +0 -5
  88. package/es/utils/global.js +0 -27
  89. package/es/utils/global.js.map +0 -1
  90. package/es/utils/id.js +0 -14
  91. package/es/utils/id.js.map +0 -1
  92. package/es/utils/index.d.ts +0 -4
  93. package/es/utils/index.js +0 -5
  94. package/es/utils/index.js.map +0 -1
  95. package/es/utils/storage.js.map +0 -1
  96. package/lib/EventEmitter.d.ts +0 -37
  97. package/lib/EventEmitter.js +0 -94
  98. package/lib/EventEmitter.js.map +0 -1
  99. package/lib/FlowModel.d.ts +0 -146
  100. package/lib/FlowModel.js +0 -236
  101. package/lib/FlowModel.js.map +0 -1
  102. package/lib/Scheduler.d.ts +0 -78
  103. package/lib/Scheduler.js +0 -179
  104. package/lib/Scheduler.js.map +0 -1
  105. package/lib/constant/index.d.ts +0 -16
  106. package/lib/constant/index.js.map +0 -1
  107. package/lib/constant/logCode.d.ts +0 -12
  108. package/lib/constant/logCode.js.map +0 -1
  109. package/lib/expression/brewserVm.d.ts +0 -2
  110. package/lib/expression/brewserVm.js +0 -33
  111. package/lib/expression/brewserVm.js.map +0 -1
  112. package/lib/expression/index.d.ts +0 -2
  113. package/lib/expression/index.js +0 -20
  114. package/lib/expression/index.js.map +0 -1
  115. package/lib/expression/nodeVm.d.ts +0 -4
  116. package/lib/expression/nodeVm.js +0 -13
  117. package/lib/expression/nodeVm.js.map +0 -1
  118. package/lib/index.d.ts +0 -157
  119. package/lib/index.js +0 -159
  120. package/lib/index.js.map +0 -1
  121. package/lib/nodes/base.d.ts +0 -108
  122. package/lib/nodes/base.js +0 -152
  123. package/lib/nodes/base.js.map +0 -1
  124. package/lib/nodes/index.d.ts +0 -3
  125. package/lib/nodes/index.js +0 -7
  126. package/lib/nodes/index.js.map +0 -1
  127. package/lib/nodes/start.d.ts +0 -6
  128. package/lib/nodes/start.js +0 -15
  129. package/lib/nodes/start.js.map +0 -1
  130. package/lib/nodes/task.d.ts +0 -6
  131. package/lib/nodes/task.js +0 -15
  132. package/lib/nodes/task.js.map +0 -1
  133. package/lib/platform/browser/browserVm.d.ts +0 -4
  134. package/lib/platform/browser/browserVm.js +0 -49
  135. package/lib/platform/browser/browserVm.js.map +0 -1
  136. package/lib/platform/browser/index.d.ts +0 -4
  137. package/lib/platform/browser/index.js +0 -28
  138. package/lib/platform/browser/index.js.map +0 -1
  139. package/lib/platform/index.d.ts +0 -1
  140. package/lib/platform/index.js +0 -5
  141. package/lib/platform/index.js.map +0 -1
  142. package/lib/platform/node/index.d.ts +0 -4
  143. package/lib/platform/node/index.js +0 -28
  144. package/lib/platform/node/index.js.map +0 -1
  145. package/lib/platform/node/nodeVm.d.ts +0 -1
  146. package/lib/platform/node/nodeVm.js +0 -13
  147. package/lib/platform/node/nodeVm.js.map +0 -1
  148. package/lib/recorder/index.d.ts +0 -46
  149. package/lib/recorder/index.js +0 -117
  150. package/lib/recorder/index.js.map +0 -1
  151. package/lib/utils/global.d.ts +0 -5
  152. package/lib/utils/global.js +0 -31
  153. package/lib/utils/global.js.map +0 -1
  154. package/lib/utils/id.d.ts +0 -3
  155. package/lib/utils/id.js +0 -20
  156. package/lib/utils/id.js.map +0 -1
  157. package/lib/utils/index.d.ts +0 -4
  158. package/lib/utils/index.js +0 -9
  159. package/lib/utils/index.js.map +0 -1
  160. package/lib/utils/storage.d.ts +0 -7
  161. package/lib/utils/storage.js.map +0 -1
  162. package/src/EventEmitter.ts +0 -103
  163. package/src/FlowModel.ts +0 -325
  164. package/src/Scheduler.ts +0 -244
  165. package/src/constant/index.ts +0 -23
  166. package/src/constant/logCode.ts +0 -34
  167. package/src/expression/brewserVm.ts +0 -36
  168. package/src/expression/index.ts +0 -17
  169. package/src/expression/nodeVm.ts +0 -14
  170. package/src/index.ts +0 -300
  171. package/src/nodes/base.ts +0 -234
  172. package/src/nodes/index.ts +0 -3
  173. package/src/nodes/start.ts +0 -8
  174. package/src/nodes/task.ts +0 -8
  175. package/src/platform/browser/browserVm.ts +0 -52
  176. package/src/platform/browser/index.ts +0 -28
  177. package/src/platform/index.ts +0 -1
  178. package/src/platform/node/index.ts +0 -28
  179. package/src/platform/node/nodeVm.ts +0 -12
  180. package/src/recorder/index.ts +0 -137
  181. package/src/typings.d.ts +0 -0
  182. package/src/utils/global.ts +0 -41
  183. package/src/utils/id.ts +0 -16
  184. package/src/utils/index.ts +0 -5
  185. package/src/utils/storage.ts +0 -55
  186. /package/es/constant/{logCode.d.ts → LogCode.d.ts} +0 -0
  187. /package/es/constant/{index.d.ts → constant.d.ts} +0 -0
  188. /package/es/{utils/id.d.ts → util/ID.d.ts} +0 -0
  189. /package/es/{utils → util}/storage.d.ts +0 -0
package/src/Scheduler.ts DELETED
@@ -1,244 +0,0 @@
1
- import { Engine } from '.'
2
- import Recorder from './recorder'
3
- import FlowModel from './FlowModel'
4
- import EventEmitter from './EventEmitter'
5
- import { createActionId } from './utils'
6
- import {
7
- EVENT_INSTANCE_ERROR,
8
- EVENT_INSTANCE_COMPLETE,
9
- EVENT_INSTANCE_INTERRUPTED,
10
- FlowStatus,
11
- } from './constant'
12
-
13
- /**
14
- * 调度器
15
- * 通过一个队列维护需要执行的节点,一个集合维护正在执行的节点
16
- */
17
- export class Scheduler extends EventEmitter {
18
- /**
19
- * 当前需要执行的节点队列
20
- */
21
- nodeQueueMap: Map<Engine.Key, Engine.NodeParam[]>
22
- /**
23
- * 当前正在执行的节点集合
24
- * 在每个节点执行完成后,会从集合中删除
25
- * 同时会判断次集合中是否还存在和此节点相同的 executionId,如果不存在,说明该流程已经执行完成
26
- */
27
- actionRunningMap: Map<Engine.Key, Scheduler.ActionParamMap>
28
- /**
29
- * 流程模型,用于创建节点模型
30
- */
31
- flowModel: FlowModel
32
- /**
33
- * 执行记录存储器
34
- * 用于存储节点执行的结果
35
- */
36
- recorder?: Recorder
37
-
38
- constructor(config: Scheduler.ISchedulerProps) {
39
- super()
40
- this.nodeQueueMap = new Map()
41
- this.actionRunningMap = new Map()
42
- this.flowModel = config.flowModel
43
- this.recorder = config.recorder
44
- }
45
-
46
- /**
47
- * 添加一个任务到队列中。
48
- * 1. 由流程模型将所有的开始及诶带你添加到队列中
49
- * 2. 当一个节点执行完成后,将后续的节点添加到队列中
50
- * @param nodeParam
51
- */
52
- public addAction(nodeParam: Engine.NodeParam) {
53
- const { executionId } = nodeParam
54
- if (!this.nodeQueueMap.has(executionId)) {
55
- this.nodeQueueMap.set(executionId, [])
56
- }
57
-
58
- const currentActionQueue: Engine.NodeParam[] | undefined =
59
- this.nodeQueueMap.get(executionId)
60
- if (currentActionQueue) {
61
- currentActionQueue.push(nodeParam)
62
- }
63
- console.log('this.nodeQueueMap--->>>', this.nodeQueueMap)
64
- }
65
-
66
- private pushActionToRunningMap(actionParam: Scheduler.ActionParam) {
67
- const { executionId, actionId } = actionParam
68
- if (!this.actionRunningMap.has(executionId)) {
69
- const runningMap: Scheduler.ActionParamMap = new Map()
70
- this.actionRunningMap.set(executionId, runningMap)
71
- }
72
- if (actionId) {
73
- this.actionRunningMap.get(executionId)?.set(actionId, actionParam)
74
- }
75
- }
76
-
77
- private removeActionFromRunningMap(actionParam: Engine.ActionParam) {
78
- const { executionId, actionId } = actionParam
79
- if (!actionId) return
80
-
81
- const runningMap = this.actionRunningMap.get(executionId)
82
- if (!runningMap) return
83
-
84
- runningMap.delete(actionId)
85
- }
86
-
87
- /**
88
- * 为了防止多次添加导致
89
- * @param actionParam
90
- */
91
- private saveActionResult(actionParam: Engine.NextActionParam) {
92
- this.recorder?.addActionRecord({
93
- timestamp: Date.now(),
94
- ...actionParam,
95
- })
96
- }
97
-
98
- private hasRunningAction(executionId: Engine.Key): boolean {
99
- const runningMap = this.actionRunningMap.get(executionId)
100
- if (!runningMap) return false
101
- if (runningMap.size === 0) {
102
- this.actionRunningMap.delete(executionId)
103
- return false
104
- }
105
- return true
106
- }
107
-
108
- /**
109
- * 调度器执行下一个任务
110
- * 1. 提供给流程模型,用户开始执行第一个任务
111
- * 2. 内部任务执行完成后,调用此方法继续执行下一个任务
112
- * 3. 当判断没有可以继续执行的任务后,触发流程结束事件
113
- * @param runParam
114
- */
115
- public run(runParam: Scheduler.ActionParam) {
116
- const nodeQueue: Engine.NodeParam[] | undefined = this.nodeQueueMap.get(
117
- runParam.executionId,
118
- )
119
-
120
- // 将同一个 executionId 当前待执行的节点一起执行
121
- // 避免出现某一个节点执行时间过长,导致其他节点等待时间过长
122
- while (nodeQueue?.length) {
123
- const currentNode = nodeQueue.pop()
124
- const actionId = createActionId()
125
- const actionParam: Engine.ActionParam = {
126
- ...(currentNode as Engine.NodeParam),
127
- actionId,
128
- }
129
- this.pushActionToRunningMap(actionParam)
130
- this.exec(actionParam)
131
- }
132
-
133
- if (!this.hasRunningAction(runParam.executionId)) {
134
- // 当一个流程在 nodeQueueMap 和 actionRunningMap 中都不存在执行的节点时,说明这个流程已经执行完成。
135
- this.emit(EVENT_INSTANCE_COMPLETE, {
136
- ...runParam,
137
- status: FlowStatus.COMPLETED,
138
- })
139
- }
140
- }
141
-
142
- private next(data: Engine.NextActionParam) {
143
- if (data.outgoing && data.outgoing.length > 0) {
144
- data.outgoing.forEach((item) => {
145
- if (item.result) {
146
- this.addAction({
147
- executionId: data.executionId,
148
- nodeId: item.target,
149
- })
150
- }
151
- })
152
- }
153
-
154
- this.saveActionResult(data)
155
- this.removeActionFromRunningMap(data)
156
- this.run(data)
157
- }
158
-
159
- /**
160
- * 恢复某个任务的执行
161
- * 可以自定义节点手动实现流程中断,然后通过此方法恢复流程的执行
162
- * @param resumeParam
163
- */
164
- public async resume(resumeParam: Engine.ResumeParam) {
165
- const { executionId, actionId, nodeId } = resumeParam
166
- this.pushActionToRunningMap({
167
- executionId,
168
- actionId,
169
- nodeId,
170
- })
171
-
172
- const model = this.flowModel.createAction(nodeId)
173
- await model?.resume({
174
- ...resumeParam,
175
- next: this.next.bind(this),
176
- })
177
- }
178
-
179
- // 中断时,触发事件
180
- private interrupted(execResult: Engine.NextActionParam) {
181
- this.emit(EVENT_INSTANCE_INTERRUPTED, execResult)
182
- }
183
- // 报错时,触发事件
184
- private error(execResult: Engine.NextActionParam) {
185
- this.emit(EVENT_INSTANCE_ERROR, execResult)
186
- }
187
-
188
- private async exec(actionParam: Engine.ActionParam) {
189
- const { executionId, actionId, nodeId } = actionParam
190
- const model = this.flowModel.createAction(nodeId)
191
- const execResult = await model?.execute({
192
- executionId,
193
- actionId,
194
- nodeId,
195
- next: this.next.bind(this),
196
- })
197
-
198
- if (execResult) {
199
- const { nodeType, properties, outgoing, status, detail } = execResult
200
- const actionResult: Engine.NextActionParam = {
201
- // actionParam
202
- executionId,
203
- actionId,
204
- nodeId,
205
- // execResult
206
- nodeType,
207
- properties,
208
- outgoing,
209
- status,
210
- detail,
211
- }
212
- if (execResult?.status === FlowStatus.INTERRUPTED) {
213
- this.interrupted(execResult)
214
- this.saveActionResult(actionResult)
215
- this.removeActionFromRunningMap(actionParam)
216
- }
217
-
218
- if (execResult?.status === FlowStatus.ERROR) {
219
- this.error(execResult)
220
- this.saveActionResult(actionResult)
221
- this.removeActionFromRunningMap(actionParam)
222
- }
223
- }
224
- // TODO: 考虑停下所有的任务
225
- }
226
- }
227
-
228
- export namespace Scheduler {
229
- export type ActionParam = {
230
- executionId: Engine.Key
231
- actionId?: Engine.Key
232
- nodeId?: Engine.Key
233
- data?: Record<string, unknown>
234
- [key: string]: unknown
235
- }
236
- export type ActionParamMap = Map<Engine.Key, ActionParam>
237
-
238
- export interface ISchedulerProps {
239
- flowModel: FlowModel
240
- recorder?: Recorder
241
- }
242
- }
243
-
244
- export default Scheduler
@@ -1,23 +0,0 @@
1
- // baseType
2
- export const BASE_START_NODE = 'start'
3
-
4
- // eventType
5
- export const EVENT_INSTANCE_COMPLETE = 'instance:complete'
6
- export const EVENT_INSTANCE_INTERRUPTED = 'instance:interrupted'
7
- export const EVENT_INSTANCE_ERROR = 'instance:error'
8
-
9
- // flowStatus
10
- export enum FlowStatus {
11
- COMPLETED = 'completed',
12
- INTERRUPTED = 'interrupted',
13
- RUNNING = 'running',
14
- PENDING = 'pending',
15
- ERROR = 'error',
16
- }
17
-
18
- // actionStatus
19
- export enum ActionStatus {
20
- SUCCESS = 'success',
21
- ERROR = 'error',
22
- INTERRUPTED = 'interrupted',
23
- }
@@ -1,34 +0,0 @@
1
- export enum ErrorCode {
2
- // 模型数据错误
3
- NONE_START_NODE = 1000,
4
- NONE_NODE_ID = 1001,
5
-
6
- // 表达式错误
7
- NO_DOCUMENT_BODY = 2001,
8
- }
9
-
10
- export enum WarningCode {
11
- NONE_START_NODE_IN_DATA = 2000,
12
- START_NODE_INCOMING = 2001,
13
-
14
- // 表达式判断异常
15
- EXPRESSION_EXEC_ERROR = 3000,
16
- }
17
-
18
- // TODO: 感觉这块可以用个国际化插件,这样配置不同语言加文件就可以了。
19
- const errorMsgMapCn = {
20
- [ErrorCode.NONE_START_NODE]: '未找到入度为0的节点',
21
- [ErrorCode.NONE_NODE_ID]: '流程数据中存在没有此节点',
22
- [ErrorCode.NO_DOCUMENT_BODY]: '找不到document.body, 请在DOM加载完成后再执行',
23
- }
24
-
25
- const warningMsgMapCn = {
26
- [WarningCode.NONE_START_NODE_IN_DATA]: '初始化数据中未找到入度为0的节点',
27
- [WarningCode.START_NODE_INCOMING]: '开始节点不允许被连入',
28
- [WarningCode.EXPRESSION_EXEC_ERROR]: '表达式执行异常',
29
- }
30
-
31
- export const getErrorMsg = (code: ErrorCode) =>
32
- `error[${code}]: ${errorMsgMapCn[code]}`
33
- export const getWarningMsg = (code: WarningCode) =>
34
- `warning[${code}]: ${warningMsgMapCn[code]}`
@@ -1,36 +0,0 @@
1
- import {
2
- ErrorCode,
3
- WarningCode,
4
- getErrorMsg,
5
- getWarningMsg,
6
- } from '../constant/logCode'
7
-
8
- const runInBrowserContext = async (code: string, globalData = {}) => {
9
- const iframe = document.createElement('iframe')
10
- iframe.style.display = 'none'
11
- if (!document || !document.body) {
12
- console.error(getErrorMsg(ErrorCode.NO_DOCUMENT_BODY))
13
- }
14
- document.body.appendChild(iframe)
15
-
16
- const iframeWindow = iframe.contentWindow as any
17
- const iframeEval = iframeWindow.eval
18
- Object.keys(globalData).forEach((key: string) => {
19
- iframeWindow[key] = globalData[key]
20
- })
21
-
22
- let res = null
23
- try {
24
- res = iframeEval.call(iframeWindow, code)
25
- } catch (e) {
26
- console.warn(getWarningMsg(WarningCode.EXPRESSION_EXEC_ERROR), {
27
- code,
28
- globalData,
29
- e,
30
- })
31
- }
32
- document.body.removeChild(iframe)
33
- return res
34
- }
35
-
36
- export { runInBrowserContext }
@@ -1,17 +0,0 @@
1
- import { runInNodeContext } from './nodeVm'
2
- import { runInBrowserContext } from './brewserVm'
3
- import { isInNodeJS, isInBrowser, globalScope } from '../utils'
4
-
5
- const getExpressionResult = async (code: string, context: any) => {
6
- if (isInNodeJS) {
7
- const r = await runInNodeContext(code, context)
8
- return r
9
- }
10
- if (isInBrowser) {
11
- const r = await runInBrowserContext(code, context)
12
- return r
13
- }
14
- return globalScope.eval(code)
15
- }
16
-
17
- export { getExpressionResult }
@@ -1,14 +0,0 @@
1
- import vm from 'node:vm'
2
- // const vm = require('node:vm');
3
-
4
- const runInNodeContext = async (
5
- code: string,
6
- globalData: Record<string, unknown> = {},
7
- ) => {
8
- const context = vm.createContext(globalData)
9
- vm.runInContext(code, context)
10
-
11
- return context
12
- }
13
-
14
- export { runInNodeContext }
package/src/index.ts DELETED
@@ -1,300 +0,0 @@
1
- // import { LogicFlow } from '@logicflow/core';
2
- import { BaseNode, StartNode, TaskNode } from './nodes'
3
- import { FlowModel } from './FlowModel'
4
- import { Recorder } from './recorder'
5
- import { createEngineId } from './utils'
6
-
7
- export class Engine {
8
- readonly instanceId: string
9
- graphData?: Engine.GraphConfigData
10
-
11
- flowModel?: FlowModel
12
- recorder?: Recorder
13
- context?: Record<string, unknown>
14
- nodeModelMap: Map<string, BaseNode.NodeConstructor>
15
-
16
- constructor(options?: Engine.Options) {
17
- this.nodeModelMap = new Map()
18
- this.instanceId = createEngineId()
19
- if (options?.debug) {
20
- this.recorder = new Recorder({
21
- instanceId: this.instanceId,
22
- })
23
- }
24
- // 默认注册节点 register default nodes
25
- this.register({
26
- type: StartNode.nodeTypeName,
27
- model: StartNode,
28
- })
29
- this.register({
30
- type: TaskNode.nodeTypeName,
31
- model: TaskNode,
32
- })
33
- this.context = options?.context || {}
34
- }
35
-
36
- /**
37
- * 注册节点
38
- * @param nodeConfig { type: 'custom-node', model: NodeClass }
39
- */
40
- register(nodeConfig: Engine.NodeConfig) {
41
- this.nodeModelMap.set(nodeConfig.type, nodeConfig.model)
42
- }
43
-
44
- /**
45
- * 自定义执行记录的存储,默认浏览器使用 sessionStorage, nodejs 使用内存存储
46
- * 注意:由于执行记录不全会主动删除,所以需要自行清理。
47
- * nodejs 环境建议自定义为持久化存储。
48
- * engine.setCustomRecorder({{
49
- * async addActionRecord(task) {}
50
- * async getTask(actionId) {}
51
- * async getExecutionTasks(executionId) {}
52
- * clear(instanceId) {}
53
- * }}
54
- * @param recorder
55
- */
56
- setCustomRecorder(recorder: Recorder) {
57
- this.recorder = recorder
58
- }
59
-
60
- /**
61
- * 加载流程图数据
62
- */
63
- load({
64
- graphData,
65
- startNodeType = 'StartNode',
66
- globalData = {},
67
- }: Engine.LoadGraphParam): FlowModel {
68
- this.graphData = graphData
69
- const flowModel = new FlowModel({
70
- nodeModelMap: this.nodeModelMap,
71
- recorder: this.recorder,
72
- context: this.context,
73
- globalData,
74
- startNodeType,
75
- })
76
-
77
- flowModel.load(graphData)
78
- this.flowModel = flowModel
79
- return flowModel
80
- }
81
-
82
- /**
83
- * 执行流程,允许多次调用
84
- */
85
- async execute(
86
- param?: Partial<Engine.ActionParam>,
87
- ): Promise<Engine.NextActionParam> {
88
- return new Promise((resolve, reject) => {
89
- let execParam = param
90
- if (!param) {
91
- execParam = {}
92
- }
93
-
94
- this.flowModel?.execute({
95
- ...execParam,
96
- callback: (result) => {
97
- resolve(result)
98
- },
99
- onError: (error) => {
100
- reject(error)
101
- },
102
- })
103
- })
104
- }
105
-
106
- /**
107
- * 中断流程恢复
108
- * @param resumeParam
109
- * @returns
110
- */
111
- async resume(
112
- resumeParam: Engine.ResumeParam,
113
- ): Promise<Engine.NextActionParam | undefined> {
114
- return new Promise((resolve, reject) => {
115
- this.flowModel?.resume({
116
- ...resumeParam,
117
- callback: (result) => {
118
- resolve(result)
119
- },
120
- onError: (error) => {
121
- reject(error)
122
- },
123
- })
124
- })
125
- }
126
-
127
- async getExecutionList() {
128
- return await this.recorder?.getExecutionList()
129
- }
130
-
131
- /**
132
- * 获取执行任务记录
133
- * @param executionId
134
- * @returns
135
- */
136
- async getExecutionRecord(
137
- executionId: Engine.Key,
138
- ): Promise<Recorder.Info[] | null> {
139
- const actions = await this.recorder?.getExecutionActions(executionId)
140
-
141
- if (!actions) {
142
- return null
143
- }
144
-
145
- // DONE: 确认 records 的类型
146
- const records: Promise<Recorder.Info>[] = []
147
- for (let i = 0; i < actions?.length; i++) {
148
- const action = actions[i]
149
- if (this.recorder) {
150
- records.push(this.recorder?.getActionRecord(action))
151
- }
152
- }
153
-
154
- return Promise.all(records)
155
- }
156
-
157
- destroy() {
158
- this.recorder?.clear()
159
- }
160
-
161
- getGlobalData() {
162
- return this.flowModel?.globalData
163
- }
164
-
165
- setGlobalData(data: Record<string, unknown>) {
166
- if (this.flowModel) {
167
- this.flowModel.globalData = data
168
- }
169
- }
170
-
171
- updateGlobalData(data: Record<string, unknown>) {
172
- if (this.flowModel) {
173
- Object.assign(this.flowModel.globalData, data)
174
- }
175
- }
176
- }
177
-
178
- export namespace Engine {
179
- export type Point = {
180
- id?: string
181
- x: number
182
- y: number
183
- [key: string]: unknown
184
- }
185
-
186
- export type TextConfig = {
187
- value: string
188
- } & Point
189
-
190
- export type NodeData = {
191
- id: string
192
- type: string
193
- x?: number
194
- y?: number
195
- text?: TextConfig | string
196
- zIndex?: number
197
- properties?: Record<string, unknown>
198
- }
199
-
200
- export type EdgeData = {
201
- id: string
202
- /**
203
- * 边的类型,不传默认为lf.setDefaultEdgeType(type)传入的类型。
204
- * LogicFlow内部默认为polyline
205
- */
206
- type?: string
207
- sourceNodeId: string
208
- sourceAnchorId?: string
209
- targetNodeId: string
210
- targetAnchorId?: string
211
- startPoint?: {
212
- x: number
213
- y: number
214
- }
215
- endPoint?: {
216
- x: number
217
- y: number
218
- }
219
- text?:
220
- | {
221
- x: number
222
- y: number
223
- value: string
224
- }
225
- | string
226
- pointsList?: Point[]
227
- zIndex?: number
228
- properties?: Record<string, unknown>
229
- }
230
-
231
- export type GraphConfigData = {
232
- nodes: NodeData[]
233
- edges: EdgeData[]
234
- }
235
-
236
- export type LoadGraphParam = {
237
- graphData: GraphConfigData
238
- startNodeType?: string
239
- globalData?: Record<string, unknown>
240
- }
241
-
242
- export type Options = {
243
- context?: Record<string, unknown>
244
- debug?: boolean
245
- }
246
- export type Key = string | number
247
- export type NodeConfig = {
248
- type: string
249
- model: any // TODO: NodeModel 可能有多个,类型该如何定义呢???
250
- }
251
-
252
- export type NodeParam = {
253
- executionId: Key
254
- nodeId: Key
255
- }
256
-
257
- export type CommonActionInfo = {
258
- actionId: Key
259
- } & NodeParam
260
-
261
- export type ActionParam = CommonActionInfo
262
-
263
- export type ResumeParam = {
264
- data?: Record<string, unknown>
265
- } & CommonActionInfo
266
-
267
- export type ExecParam = {
268
- next: (data: NextActionParam) => void
269
- } & ActionParam
270
-
271
- export type ExecResumeParam = {
272
- next: (data: NextActionParam) => void
273
- } & ResumeParam
274
-
275
- export type ActionStatus = 'success' | 'error' | 'interrupted' | '' // ??? Question: '' 状态是什么状态
276
-
277
- export type NextActionParam = {
278
- executionId: Key
279
- nodeId: Key
280
- actionId: Key
281
- nodeType: string
282
- outgoing: BaseNode.OutgoingConfig[]
283
- properties?: Record<string, unknown>
284
- detail?: Record<string, unknown>
285
- status?: ActionStatus
286
- }
287
-
288
- export type ActionResult = NextActionParam
289
-
290
- export type NodeExecResult = {
291
- nodeType: string
292
- properties?: Record<string, unknown>
293
- } & CommonActionInfo &
294
- ActionResult
295
- }
296
-
297
- export * from './constant'
298
- export { BaseNode, StartNode, TaskNode, Recorder }
299
-
300
- export default Engine