@logicflow/engine 0.0.11-beta.0 → 0.0.12-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 (170) hide show
  1. package/README.md +5 -2
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -0
  4. package/es/EventEmitter.d.ts +34 -4
  5. package/es/EventEmitter.js +70 -48
  6. package/es/EventEmitter.js.map +1 -0
  7. package/es/FlowModel.d.ts +75 -73
  8. package/es/FlowModel.js +130 -173
  9. package/es/FlowModel.js.map +1 -0
  10. package/es/Scheduler.d.ts +50 -34
  11. package/es/Scheduler.js +134 -209
  12. package/es/Scheduler.js.map +1 -0
  13. package/es/constant/{constant.js → index.js} +8 -7
  14. package/es/constant/index.js.map +1 -0
  15. package/es/constant/logCode.js +29 -0
  16. package/es/constant/logCode.js.map +1 -0
  17. package/es/index.d.ts +135 -38
  18. package/es/index.js +92 -144
  19. package/es/index.js.map +1 -0
  20. package/es/nodes/base.d.ts +108 -0
  21. package/es/nodes/base.js +151 -0
  22. package/es/nodes/base.js.map +1 -0
  23. package/es/nodes/index.d.ts +3 -0
  24. package/es/nodes/index.js +4 -0
  25. package/es/nodes/index.js.map +1 -0
  26. package/es/nodes/{StartNode.d.ts → start.d.ts} +3 -2
  27. package/es/nodes/start.js +11 -0
  28. package/es/nodes/start.js.map +1 -0
  29. package/es/nodes/{TaskNode.d.ts → task.d.ts} +3 -2
  30. package/es/nodes/task.js +11 -0
  31. package/es/nodes/task.js.map +1 -0
  32. package/es/platform/browser/browserVm.d.ts +1 -0
  33. package/es/platform/browser/browserVm.js +66 -0
  34. package/es/platform/browser/browserVm.js.map +1 -0
  35. package/es/platform/browser/index.d.ts +4 -0
  36. package/es/platform/browser/index.js +23 -0
  37. package/es/platform/browser/index.js.map +1 -0
  38. package/es/platform/index.d.ts +1 -0
  39. package/es/platform/index.js +2 -0
  40. package/es/platform/index.js.map +1 -0
  41. package/es/platform/node/index.d.ts +4 -0
  42. package/es/platform/node/index.js +23 -0
  43. package/es/platform/node/index.js.map +1 -0
  44. package/es/platform/node/nodeVm.d.ts +1 -0
  45. package/es/platform/node/nodeVm.js +9 -0
  46. package/es/platform/node/nodeVm.js.map +1 -0
  47. package/es/recorder/index.d.ts +36 -10
  48. package/es/recorder/index.js +82 -135
  49. package/es/recorder/index.js.map +1 -0
  50. package/es/utils/global.d.ts +5 -0
  51. package/es/utils/global.js +27 -0
  52. package/es/utils/global.js.map +1 -0
  53. package/es/utils/id.js +14 -0
  54. package/es/utils/id.js.map +1 -0
  55. package/es/utils/index.d.ts +4 -0
  56. package/es/utils/index.js +5 -0
  57. package/es/utils/index.js.map +1 -0
  58. package/es/{util → utils}/storage.js +17 -16
  59. package/es/utils/storage.js.map +1 -0
  60. package/lib/EventEmitter.d.ts +37 -0
  61. package/lib/EventEmitter.js +94 -0
  62. package/lib/EventEmitter.js.map +1 -0
  63. package/lib/FlowModel.d.ts +146 -0
  64. package/lib/FlowModel.js +236 -0
  65. package/lib/FlowModel.js.map +1 -0
  66. package/lib/Scheduler.d.ts +78 -0
  67. package/lib/Scheduler.js +179 -0
  68. package/lib/Scheduler.js.map +1 -0
  69. package/lib/constant/index.d.ts +16 -0
  70. package/{cjs/constant/constant.js → lib/constant/index.js} +4 -3
  71. package/lib/constant/index.js.map +1 -0
  72. package/lib/constant/logCode.d.ts +12 -0
  73. package/{cjs/constant/LogCode.js → lib/constant/logCode.js} +16 -13
  74. package/lib/constant/logCode.js.map +1 -0
  75. package/lib/index.d.ts +157 -0
  76. package/lib/index.js +159 -0
  77. package/lib/index.js.map +1 -0
  78. package/lib/nodes/base.d.ts +108 -0
  79. package/lib/nodes/base.js +154 -0
  80. package/lib/nodes/base.js.map +1 -0
  81. package/lib/nodes/index.d.ts +3 -0
  82. package/lib/nodes/index.js +7 -0
  83. package/lib/nodes/index.js.map +1 -0
  84. package/lib/nodes/start.d.ts +6 -0
  85. package/lib/nodes/start.js +15 -0
  86. package/lib/nodes/start.js.map +1 -0
  87. package/lib/nodes/task.d.ts +6 -0
  88. package/lib/nodes/task.js +15 -0
  89. package/lib/nodes/task.js.map +1 -0
  90. package/lib/platform/browser/browserVm.d.ts +1 -0
  91. package/lib/platform/browser/browserVm.js +70 -0
  92. package/lib/platform/browser/browserVm.js.map +1 -0
  93. package/lib/platform/browser/index.d.ts +4 -0
  94. package/lib/platform/browser/index.js +28 -0
  95. package/lib/platform/browser/index.js.map +1 -0
  96. package/lib/platform/index.d.ts +1 -0
  97. package/lib/platform/index.js +5 -0
  98. package/lib/platform/index.js.map +1 -0
  99. package/lib/platform/node/index.d.ts +4 -0
  100. package/lib/platform/node/index.js +28 -0
  101. package/lib/platform/node/index.js.map +1 -0
  102. package/lib/platform/node/nodeVm.d.ts +1 -0
  103. package/lib/platform/node/nodeVm.js +13 -0
  104. package/lib/platform/node/nodeVm.js.map +1 -0
  105. package/lib/recorder/index.d.ts +46 -0
  106. package/lib/recorder/index.js +117 -0
  107. package/lib/recorder/index.js.map +1 -0
  108. package/lib/utils/global.d.ts +5 -0
  109. package/lib/utils/global.js +31 -0
  110. package/lib/utils/global.js.map +1 -0
  111. package/lib/utils/id.d.ts +3 -0
  112. package/lib/utils/id.js +20 -0
  113. package/lib/utils/id.js.map +1 -0
  114. package/lib/utils/index.d.ts +4 -0
  115. package/lib/utils/index.js +9 -0
  116. package/lib/utils/index.js.map +1 -0
  117. package/lib/utils/storage.d.ts +7 -0
  118. package/{cjs/util → lib/utils}/storage.js +18 -17
  119. package/lib/utils/storage.js.map +1 -0
  120. package/package.json +31 -71
  121. package/src/EventEmitter.ts +103 -0
  122. package/src/FlowModel.ts +325 -0
  123. package/src/Scheduler.ts +244 -0
  124. package/src/constant/index.ts +23 -0
  125. package/src/constant/logCode.ts +34 -0
  126. package/src/index.ts +300 -0
  127. package/src/nodes/base.ts +236 -0
  128. package/src/nodes/index.ts +3 -0
  129. package/src/nodes/start.ts +8 -0
  130. package/src/nodes/task.ts +8 -0
  131. package/src/platform/browser/browserVm.ts +68 -0
  132. package/src/platform/browser/index.ts +28 -0
  133. package/src/platform/index.ts +1 -0
  134. package/src/platform/node/index.ts +28 -0
  135. package/src/platform/node/nodeVm.ts +12 -0
  136. package/src/recorder/index.ts +137 -0
  137. package/src/typings.d.ts +0 -0
  138. package/src/utils/global.ts +41 -0
  139. package/src/utils/id.ts +16 -0
  140. package/src/utils/index.ts +5 -0
  141. package/src/utils/storage.ts +55 -0
  142. package/cjs/EventEmitter.js +0 -70
  143. package/cjs/FlowModel.js +0 -277
  144. package/cjs/Scheduler.js +0 -252
  145. package/cjs/expression/browserVm.js +0 -81
  146. package/cjs/expression/index.js +0 -57
  147. package/cjs/index.js +0 -210
  148. package/cjs/nodes/BaseNode.js +0 -252
  149. package/cjs/nodes/StartNode.js +0 -27
  150. package/cjs/nodes/TaskNode.js +0 -27
  151. package/cjs/recorder/index.js +0 -168
  152. package/cjs/util/ID.js +0 -16
  153. package/cjs/util/global.js +0 -32
  154. package/es/constant/LogCode.js +0 -28
  155. package/es/expression/browserVm.d.ts +0 -4
  156. package/es/expression/browserVm.js +0 -76
  157. package/es/expression/index.d.ts +0 -2
  158. package/es/expression/index.js +0 -54
  159. package/es/nodes/BaseNode.d.ts +0 -110
  160. package/es/nodes/BaseNode.js +0 -250
  161. package/es/nodes/StartNode.js +0 -25
  162. package/es/nodes/TaskNode.js +0 -25
  163. package/es/util/ID.js +0 -13
  164. package/es/util/global.d.ts +0 -5
  165. package/es/util/global.js +0 -26
  166. package/lib/main.js +0 -1
  167. /package/es/constant/{constant.d.ts → index.d.ts} +0 -0
  168. /package/es/constant/{LogCode.d.ts → logCode.d.ts} +0 -0
  169. /package/es/{util/ID.d.ts → utils/id.d.ts} +0 -0
  170. /package/es/{util → utils}/storage.d.ts +0 -0
package/src/index.ts ADDED
@@ -0,0 +1,300 @@
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
@@ -0,0 +1,236 @@
1
+ import { Engine } from '..'
2
+ import { ActionStatus } from '../constant'
3
+ import { getExpressionResult } from '../platform'
4
+
5
+ export interface IBaseNodeProps {
6
+ nodeConfig: BaseNode.NodeConfig
7
+ context: Record<string, any>
8
+ globalData: Record<string, unknown>
9
+ }
10
+
11
+ export class BaseNode implements BaseNode.Base {
12
+ readonly baseType: string
13
+ static nodeTypeName = 'BaseNode'
14
+
15
+ /**
16
+ * 节点的入边
17
+ */
18
+ incoming: BaseNode.IncomingConfig[]
19
+ /**
20
+ * 节点的出边
21
+ */
22
+ outgoing: BaseNode.OutgoingConfig[]
23
+ /**
24
+ * 节点的属性
25
+ */
26
+ properties?: Record<string, unknown>
27
+ nodeId: Engine.Key
28
+ type: string
29
+ /**
30
+ * 节点的上下文,是调用流程时传入的上下文
31
+ */
32
+ context: Record<string, any>
33
+ /**
34
+ * 节点的全局数据,是调用流程时传入的全局数据
35
+ * 在计算表达式时,即基于全局数据进行计算
36
+ */
37
+ globalData: Record<string, unknown>
38
+
39
+ constructor({ nodeConfig, context, globalData }: IBaseNodeProps) {
40
+ const { outgoing, incoming, id, type, properties } = nodeConfig
41
+ this.baseType = 'base'
42
+ this.outgoing = outgoing
43
+ this.incoming = incoming
44
+ this.nodeId = id
45
+ this.type = type
46
+ this.properties = properties
47
+
48
+ this.context = context
49
+ this.globalData = globalData
50
+ }
51
+
52
+ /**
53
+ * 节点的执行逻辑
54
+ * @overridable 可以自定义节点重写此方法
55
+ * @param param.executionId 流程执行记录 ID
56
+ * @param param.actionId 此节点执行记录 ID
57
+ * @param param.nodeId 节点 ID
58
+ * @return 返回下一步的执行参数
59
+ * 当不返回时,表示此节点执行成功,流程会继续执行下一步。
60
+ * 当返回时,返回格式为
61
+ */
62
+ public async action(
63
+ param?: Engine.ActionParam,
64
+ ): Promise<BaseNode.ActionResult | undefined> {
65
+ console.log('action param --->>>', param)
66
+ return undefined
67
+ }
68
+
69
+ /**
70
+ * 节点重新恢复执行的逻辑
71
+ * @overridable 可以自定义节点重写此方法
72
+ * @param params.executionId 流程执行记录 ID
73
+ * @param params.actionId 此节点执行记录 ID
74
+ * @param params.nodeId 节点 ID
75
+ */
76
+ public async onResume(params: Engine.ResumeParam): Promise<void> {
77
+ console.log('onResume params --->>>', params)
78
+ return undefined
79
+ }
80
+
81
+ /**
82
+ * 判断该节点是否满足条件
83
+ */
84
+ private async isPass(properties?: Record<string, unknown>): Promise<boolean> {
85
+ if (!properties) return true
86
+
87
+ const { conditionExpression } = properties
88
+ if (!conditionExpression) return true
89
+
90
+ try {
91
+ // bug:uuid 创建的 NodeId 为 xxxx-xxxx-xxxx-zzzz 格式,eval 执行时会将 - 识别为数学减号,导致执行报错
92
+ // 解决方案: 赋值变量直接命名为 isPassResult, 因为每次执行 getExpressionResult 时,都会重新射程一个 context
93
+ return await getExpressionResult(
94
+ `
95
+ const isPassResult = (${conditionExpression})
96
+ return isPassResult
97
+ `,
98
+ {
99
+ ...this.globalData,
100
+ },
101
+ )
102
+ } catch (error) {
103
+ return false
104
+ }
105
+ }
106
+
107
+ /**
108
+ * 获取当前节点执行的下一个节点
109
+ */
110
+ private async getOutgoing(): Promise<BaseNode.OutgoingConfig[]> {
111
+ const outgoing: BaseNode.OutgoingConfig[] = []
112
+ const expressions: any = []
113
+ for (const item of this.outgoing) {
114
+ const { properties } = item
115
+ expressions.push(this.isPass(properties))
116
+ }
117
+
118
+ const result = await Promise.all(expressions)
119
+ result.forEach((item, index) => {
120
+ const out = this.outgoing[index]
121
+ out.result = item
122
+ outgoing.push(out)
123
+ })
124
+ return outgoing
125
+ }
126
+
127
+ /**
128
+ * 节点的每一次执行都会生成一个唯一的 actionId
129
+ */
130
+ public async execute(
131
+ params: Engine.ExecParam,
132
+ ): Promise<Engine.NextActionParam> {
133
+ const { executionId, actionId } = params
134
+ const res = await this.action({
135
+ nodeId: this.nodeId,
136
+ executionId,
137
+ actionId,
138
+ })
139
+ const status = res ? res.status : 'success'
140
+
141
+ if (status === ActionStatus.SUCCESS) {
142
+ const outgoing = await this.getOutgoing()
143
+ const detail = res ? res.detail : {}
144
+ params.next({
145
+ status: ActionStatus.SUCCESS,
146
+ detail,
147
+ nodeId: this.nodeId,
148
+ nodeType: this.type,
149
+ properties: this.properties,
150
+ executionId,
151
+ actionId,
152
+ outgoing,
153
+ })
154
+ }
155
+
156
+ return {
157
+ status,
158
+ detail: res?.detail,
159
+ executionId,
160
+ actionId,
161
+ nodeId: this.nodeId,
162
+ nodeType: this.type,
163
+ properties: this.properties,
164
+ outgoing: [],
165
+ }
166
+ }
167
+
168
+ public async resume(params: Engine.ExecResumeParam): Promise<undefined> {
169
+ const outgoing = await this.getOutgoing()
170
+ await this.onResume({
171
+ executionId: params.executionId,
172
+ actionId: params.actionId,
173
+ nodeId: params.nodeId,
174
+ data: params.data,
175
+ })
176
+
177
+ params.next({
178
+ executionId: params.executionId,
179
+ actionId: params.actionId,
180
+ nodeId: this.nodeId,
181
+ nodeType: this.type,
182
+ properties: this.properties,
183
+ outgoing,
184
+ status: ActionStatus.SUCCESS,
185
+ })
186
+ return undefined
187
+ }
188
+ }
189
+
190
+ export namespace BaseNode {
191
+ export interface Base {
192
+ incoming: IncomingConfig[]
193
+ outgoing: OutgoingConfig[]
194
+ properties?: Record<string, unknown>
195
+ nodeId: Engine.Key
196
+ type: string
197
+ readonly baseType: string
198
+ execute(actionParam: Engine.ActionParam): Promise<Engine.NextActionParam>
199
+ }
200
+
201
+ export type IncomingConfig = {
202
+ id: Engine.Key
203
+ source: string
204
+ properties?: Record<string, unknown>
205
+ }
206
+
207
+ export type OutgoingConfig = {
208
+ id: Engine.Key
209
+ target: string
210
+ properties?: Record<string, unknown>
211
+ result?: string | boolean
212
+ }
213
+
214
+ export type NodeConfig = {
215
+ id: Engine.Key
216
+ type: string
217
+ properties?: Record<string, unknown>
218
+ incoming: IncomingConfig[]
219
+ outgoing: OutgoingConfig[]
220
+ }
221
+
222
+ export type NodeConstructor = {
223
+ new (config: {
224
+ nodeConfig: NodeConfig
225
+ context: Record<string, any>
226
+ globalData: Record<string, unknown>
227
+ }): BaseNode
228
+ }
229
+
230
+ export type ActionResult = {
231
+ status: ActionStatus
232
+ detail?: Record<string, unknown>
233
+ }
234
+ }
235
+
236
+ export default BaseNode
@@ -0,0 +1,3 @@
1
+ export * from './base'
2
+ export * from './start'
3
+ export * from './task'
@@ -0,0 +1,8 @@
1
+ import BaseNode from './base'
2
+
3
+ export default class StartNode extends BaseNode {
4
+ readonly baseType = 'start'
5
+ static nodeTypeName = 'StartNode'
6
+ }
7
+
8
+ export { StartNode }
@@ -0,0 +1,8 @@
1
+ import BaseNode from './base'
2
+
3
+ export default class TaskNode extends BaseNode {
4
+ readonly baseType = 'task'
5
+ static nodeTypeName = 'TaskNode'
6
+ }
7
+
8
+ export { TaskNode }
@@ -0,0 +1,68 @@
1
+ // import {
2
+ // ErrorCode,
3
+ // getErrorMsg,
4
+ // getWarningMsg,
5
+ // WarningCode,
6
+ // } from '../../constant/logCode'
7
+ //
8
+ // const createContext = (globalData: Record<string, unknown>) => {
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
+ // const iframeWindow = iframe.contentWindow
16
+ // if (iframeWindow) {
17
+ // // TODO: 确认是否需要该代码,parent 置为空是为了解决什么问题
18
+ // // @ts-ignore
19
+ // ;(iframeWindow!.parent as any) = null
20
+ // Object.keys(globalData).forEach((key) => {
21
+ // iframeWindow[key] = globalData[key]
22
+ // })
23
+ // }
24
+ // return iframeWindow
25
+ // }
26
+ //
27
+ // const runInContext = (code: string, context: any) => {
28
+ // try {
29
+ // const iframeEval = context.eval
30
+ // iframeEval.call(context, code)
31
+ // console.log('context --->>> ===>>>', context)
32
+ // if (context.frameElement) {
33
+ // document.body.removeChild(context.frameElement)
34
+ // }
35
+ // } catch (e) {
36
+ // console.warn(getWarningMsg(WarningCode.EXPRESSION_EXEC_ERROR), {
37
+ // code,
38
+ // context,
39
+ // e,
40
+ // })
41
+ // }
42
+ // }
43
+ //
44
+ // const runInBrowserContext = async (
45
+ // code: string,
46
+ // globalData = {},
47
+ // ): Promise<any> => {
48
+ // const context = createContext(globalData)
49
+ // runInContext(code, context)
50
+ // return context
51
+ // }
52
+ //
53
+ // export { createContext, runInContext, runInBrowserContext }
54
+
55
+ import Sandbox from '@nyariv/sandboxjs'
56
+
57
+ export const runInBrowserContext = async (
58
+ code: string,
59
+ globalData = {},
60
+ ): Promise<any> => {
61
+ try {
62
+ const sandbox = new Sandbox()
63
+ const exec = sandbox.compile(code)
64
+ return await exec(globalData).run()
65
+ } catch (e) {
66
+ console.log('runInBrowserContext error --->>>', e)
67
+ }
68
+ }
@@ -0,0 +1,28 @@
1
+ import { runInBrowserContext } from './browserVm'
2
+
3
+ const isInBrowser = typeof window === 'object' && window.window === window
4
+
5
+ const globalScope: any = (() => {
6
+ if (isInBrowser) {
7
+ return window
8
+ }
9
+
10
+ if (typeof self === 'object' && self.self === self) {
11
+ return self
12
+ }
13
+
14
+ if (typeof globalThis === 'object') {
15
+ return globalThis
16
+ }
17
+
18
+ return {
19
+ eval: () => undefined,
20
+ } as Record<string, unknown>
21
+ })()
22
+
23
+ const getExpressionResult = async (code: string, context: any) => {
24
+ const r = await runInBrowserContext(code, context)
25
+ return r
26
+ }
27
+
28
+ export { isInBrowser, globalScope, getExpressionResult }
@@ -0,0 +1 @@
1
+ export * from './node'
@@ -0,0 +1,28 @@
1
+ import { runInNodeContext } from './nodeVm'
2
+
3
+ const isInNodeJS = typeof global === 'object' && global.global === global
4
+
5
+ const globalScope: any = (() => {
6
+ if (typeof self === 'object' && self.self === self) {
7
+ return self
8
+ }
9
+
10
+ if (isInNodeJS) {
11
+ return global
12
+ }
13
+
14
+ if (typeof globalThis === 'object') {
15
+ return globalThis
16
+ }
17
+
18
+ return {
19
+ eval: () => undefined,
20
+ } as Record<string, unknown>
21
+ })()
22
+
23
+ const getExpressionResult = async (code: string, context: any) => {
24
+ const r = await runInNodeContext(code, context)
25
+ return r
26
+ }
27
+
28
+ export { isInNodeJS, globalScope, getExpressionResult }
@@ -0,0 +1,12 @@
1
+ import vm from 'node:vm'
2
+ // const vm = require('node:vm');
3
+
4
+ export const runInNodeContext = async (
5
+ code: string,
6
+ globalData: Record<string, unknown> = {},
7
+ ): Promise<any> => {
8
+ const context = vm.createContext(globalData)
9
+ vm.runInContext(code, context)
10
+
11
+ return context
12
+ }