@nocobase/flow-engine 2.1.0-alpha.1 → 2.1.0-alpha.10

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 (283) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/BlockScopedFlowEngine.js +0 -1
  4. package/lib/FlowDefinition.d.ts +2 -0
  5. package/lib/JSRunner.d.ts +15 -0
  6. package/lib/JSRunner.js +82 -7
  7. package/lib/ViewScopedFlowEngine.js +8 -1
  8. package/lib/acl/Acl.js +13 -3
  9. package/lib/components/FlowContextSelector.js +155 -10
  10. package/lib/components/MobilePopup.js +6 -5
  11. package/lib/components/dnd/gridDragPlanner.d.ts +1 -0
  12. package/lib/components/dnd/gridDragPlanner.js +59 -3
  13. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
  14. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +76 -15
  15. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +24 -4
  16. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +21 -3
  17. package/lib/components/subModel/AddSubModelButton.js +16 -1
  18. package/lib/components/subModel/utils.js +2 -2
  19. package/lib/components/variables/VariableInput.js +9 -4
  20. package/lib/components/variables/VariableTag.js +46 -39
  21. package/lib/components/variables/utils.d.ts +7 -0
  22. package/lib/components/variables/utils.js +42 -2
  23. package/lib/data-source/index.d.ts +7 -27
  24. package/lib/data-source/index.js +84 -51
  25. package/lib/executor/FlowExecutor.d.ts +2 -1
  26. package/lib/executor/FlowExecutor.js +190 -26
  27. package/lib/flowContext.d.ts +230 -7
  28. package/lib/flowContext.js +2270 -148
  29. package/lib/flowEngine.d.ts +160 -1
  30. package/lib/flowEngine.js +383 -26
  31. package/lib/flowI18n.js +6 -4
  32. package/lib/flowSettings.d.ts +14 -6
  33. package/lib/flowSettings.js +51 -17
  34. package/lib/index.d.ts +7 -1
  35. package/lib/index.js +21 -0
  36. package/lib/lazy-helper.d.ts +14 -0
  37. package/lib/lazy-helper.js +71 -0
  38. package/lib/locale/en-US.json +9 -2
  39. package/lib/locale/index.d.ts +14 -0
  40. package/lib/locale/zh-CN.json +8 -1
  41. package/lib/models/CollectionFieldModel.d.ts +1 -0
  42. package/lib/models/CollectionFieldModel.js +3 -2
  43. package/lib/models/flowModel.d.ts +7 -0
  44. package/lib/models/flowModel.js +83 -8
  45. package/lib/provider.js +7 -6
  46. package/lib/resources/baseRecordResource.d.ts +5 -0
  47. package/lib/resources/baseRecordResource.js +24 -0
  48. package/lib/resources/multiRecordResource.d.ts +1 -0
  49. package/lib/resources/multiRecordResource.js +11 -4
  50. package/lib/resources/singleRecordResource.js +2 -0
  51. package/lib/resources/sqlResource.d.ts +4 -3
  52. package/lib/resources/sqlResource.js +8 -3
  53. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +12 -2
  54. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +2 -2
  55. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
  56. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
  57. package/lib/runjs-context/contexts/JSItemRunJSContext.js +12 -2
  58. package/lib/runjs-context/contexts/base.js +706 -41
  59. package/lib/runjs-context/contributions.d.ts +33 -0
  60. package/lib/runjs-context/contributions.js +88 -0
  61. package/lib/runjs-context/helpers.js +12 -1
  62. package/lib/runjs-context/registry.d.ts +1 -1
  63. package/lib/runjs-context/setup.js +22 -9
  64. package/lib/runjs-context/snippets/global/api-request.snippet.js +3 -3
  65. package/lib/runjs-context/snippets/global/import-esm.snippet.js +2 -3
  66. package/lib/runjs-context/snippets/global/query-selector.snippet.js +8 -3
  67. package/lib/runjs-context/snippets/global/require-amd.snippet.js +1 -1
  68. package/lib/runjs-context/snippets/index.d.ts +11 -1
  69. package/lib/runjs-context/snippets/index.js +61 -40
  70. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.js +10 -7
  71. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +3 -3
  72. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +2 -2
  73. package/lib/runjs-context/snippets/scene/block/echarts-init.snippet.js +2 -2
  74. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +2 -2
  75. package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +1 -1
  76. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +1 -1
  77. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +1 -1
  78. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +5 -5
  79. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +6 -6
  80. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +3 -4
  81. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.js +1 -1
  82. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.js +20 -3
  83. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.js +1 -1
  84. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.js +1 -1
  85. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +3 -3
  86. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +3 -3
  87. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +2 -2
  88. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +1 -1
  89. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.js +2 -2
  90. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +6 -3
  91. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +3 -1
  92. package/lib/runjsLibs.d.ts +28 -0
  93. package/lib/runjsLibs.js +532 -0
  94. package/lib/scheduler/ModelOperationScheduler.d.ts +7 -1
  95. package/lib/scheduler/ModelOperationScheduler.js +28 -23
  96. package/lib/types.d.ts +63 -1
  97. package/lib/utils/associationObjectVariable.d.ts +2 -2
  98. package/lib/utils/createCollectionContextMeta.js +1 -0
  99. package/lib/utils/createEphemeralContext.js +2 -2
  100. package/lib/utils/dateVariable.d.ts +16 -0
  101. package/lib/utils/dateVariable.js +380 -0
  102. package/lib/utils/exceptions.d.ts +7 -0
  103. package/lib/utils/exceptions.js +10 -0
  104. package/lib/utils/index.d.ts +8 -3
  105. package/lib/utils/index.js +49 -0
  106. package/lib/utils/params-resolvers.js +16 -9
  107. package/lib/utils/parsePathnameToViewParams.js +1 -1
  108. package/lib/utils/resolveModuleUrl.d.ts +58 -0
  109. package/lib/utils/resolveModuleUrl.js +65 -0
  110. package/lib/utils/resolveRunJSObjectValues.d.ts +16 -0
  111. package/lib/utils/resolveRunJSObjectValues.js +61 -0
  112. package/lib/utils/runjsModuleLoader.d.ts +58 -0
  113. package/lib/utils/runjsModuleLoader.js +422 -0
  114. package/lib/utils/runjsTemplateCompat.d.ts +35 -0
  115. package/lib/utils/runjsTemplateCompat.js +743 -0
  116. package/lib/utils/runjsValue.d.ts +29 -0
  117. package/lib/utils/runjsValue.js +275 -0
  118. package/lib/utils/safeGlobals.d.ts +18 -8
  119. package/lib/utils/safeGlobals.js +164 -17
  120. package/lib/utils/schema-utils.d.ts +17 -1
  121. package/lib/utils/schema-utils.js +80 -0
  122. package/lib/views/FlowView.d.ts +7 -1
  123. package/lib/views/createViewMeta.d.ts +0 -7
  124. package/lib/views/createViewMeta.js +19 -70
  125. package/lib/views/index.d.ts +1 -2
  126. package/lib/views/index.js +4 -3
  127. package/lib/views/runViewBeforeClose.d.ts +10 -0
  128. package/lib/views/runViewBeforeClose.js +45 -0
  129. package/lib/views/useDialog.d.ts +2 -1
  130. package/lib/views/useDialog.js +28 -6
  131. package/lib/views/useDrawer.d.ts +2 -1
  132. package/lib/views/useDrawer.js +27 -5
  133. package/lib/views/usePage.d.ts +6 -1
  134. package/lib/views/usePage.js +53 -9
  135. package/lib/views/usePopover.js +4 -1
  136. package/lib/views/viewEvents.d.ts +17 -0
  137. package/lib/views/viewEvents.js +90 -0
  138. package/package.json +5 -5
  139. package/src/BlockScopedFlowEngine.ts +2 -5
  140. package/src/JSRunner.ts +111 -5
  141. package/src/ViewScopedFlowEngine.ts +8 -0
  142. package/src/__tests__/JSRunner.test.ts +91 -1
  143. package/src/__tests__/createViewMeta.popup.test.ts +62 -1
  144. package/src/__tests__/flowContext.test.ts +693 -1
  145. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
  146. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  147. package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
  148. package/src/__tests__/flowRunJSContextDefine.test.ts +63 -0
  149. package/src/__tests__/flowRuntimeContext.test.ts +2 -1
  150. package/src/__tests__/flowSettings.open.test.tsx +123 -19
  151. package/src/__tests__/flowSettings.test.ts +94 -15
  152. package/src/__tests__/provider.test.tsx +0 -5
  153. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  154. package/src/__tests__/runjsContext.test.ts +23 -7
  155. package/src/__tests__/runjsContextImplementations.test.ts +34 -3
  156. package/src/__tests__/runjsContextRuntime.test.ts +3 -3
  157. package/src/__tests__/runjsContributions.test.ts +89 -0
  158. package/src/__tests__/runjsExternalLibs.test.ts +242 -0
  159. package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
  160. package/src/__tests__/runjsLocales.test.ts +4 -1
  161. package/src/__tests__/runjsPreprocessDefault.test.ts +72 -0
  162. package/src/__tests__/runjsRuntimeFeatures.test.ts +166 -0
  163. package/src/__tests__/runjsSnippets.test.ts +40 -3
  164. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  165. package/src/acl/Acl.tsx +3 -3
  166. package/src/components/FlowContextSelector.tsx +208 -12
  167. package/src/components/MobilePopup.tsx +4 -2
  168. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +3 -3
  169. package/src/components/__tests__/gridDragPlanner.test.ts +229 -1
  170. package/src/components/dnd/gridDragPlanner.ts +68 -2
  171. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
  172. package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
  173. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +109 -16
  174. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +41 -7
  175. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +31 -4
  176. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +157 -5
  177. package/src/components/subModel/AddSubModelButton.tsx +17 -1
  178. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +142 -32
  179. package/src/components/subModel/utils.ts +1 -1
  180. package/src/components/variables/VariableInput.tsx +12 -4
  181. package/src/components/variables/VariableTag.tsx +54 -45
  182. package/src/components/variables/__tests__/FlowContextSelector.test.tsx +260 -3
  183. package/src/components/variables/__tests__/VariableTag.test.tsx +50 -0
  184. package/src/components/variables/__tests__/utils.test.ts +81 -3
  185. package/src/components/variables/utils.ts +67 -6
  186. package/src/data-source/index.ts +88 -110
  187. package/src/executor/FlowExecutor.ts +230 -28
  188. package/src/executor/__tests__/flowExecutor.test.ts +123 -0
  189. package/src/flowContext.ts +2989 -212
  190. package/src/flowEngine.ts +427 -22
  191. package/src/flowI18n.ts +7 -5
  192. package/src/flowSettings.ts +58 -18
  193. package/src/index.ts +14 -1
  194. package/src/lazy-helper.tsx +57 -0
  195. package/src/locale/en-US.json +9 -2
  196. package/src/locale/zh-CN.json +8 -1
  197. package/src/models/CollectionFieldModel.tsx +3 -1
  198. package/src/models/__tests__/dispatchEvent.when.test.ts +768 -0
  199. package/src/models/__tests__/flowModel.clone.test.ts +416 -0
  200. package/src/models/__tests__/flowModel.test.ts +20 -4
  201. package/src/models/flowModel.tsx +112 -7
  202. package/src/provider.tsx +9 -7
  203. package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
  204. package/src/resources/__tests__/sqlResource.test.ts +60 -0
  205. package/src/resources/baseRecordResource.ts +31 -0
  206. package/src/resources/multiRecordResource.ts +11 -4
  207. package/src/resources/singleRecordResource.ts +3 -0
  208. package/src/resources/sqlResource.ts +11 -6
  209. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +10 -0
  210. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +6 -2
  211. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
  212. package/src/runjs-context/contexts/JSItemRunJSContext.ts +10 -0
  213. package/src/runjs-context/contexts/base.ts +715 -44
  214. package/src/runjs-context/contributions.ts +88 -0
  215. package/src/runjs-context/helpers.ts +11 -1
  216. package/src/runjs-context/registry.ts +1 -1
  217. package/src/runjs-context/setup.ts +24 -9
  218. package/src/runjs-context/snippets/global/api-request.snippet.ts +3 -3
  219. package/src/runjs-context/snippets/global/import-esm.snippet.ts +2 -3
  220. package/src/runjs-context/snippets/global/query-selector.snippet.ts +8 -3
  221. package/src/runjs-context/snippets/global/require-amd.snippet.ts +1 -1
  222. package/src/runjs-context/snippets/index.ts +75 -41
  223. package/src/runjs-context/snippets/scene/block/add-event-listener.snippet.ts +11 -13
  224. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +3 -3
  225. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +2 -2
  226. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +2 -2
  227. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +2 -2
  228. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +1 -1
  229. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +1 -1
  230. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +1 -1
  231. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +6 -11
  232. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +6 -6
  233. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +3 -4
  234. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +1 -1
  235. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +20 -3
  236. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +1 -1
  237. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +1 -1
  238. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +3 -3
  239. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +3 -3
  240. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +2 -2
  241. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +1 -1
  242. package/src/runjs-context/snippets/scene/form/render-basic.snippet.ts +3 -8
  243. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +6 -3
  244. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +3 -1
  245. package/src/runjsLibs.ts +622 -0
  246. package/src/scheduler/ModelOperationScheduler.ts +41 -24
  247. package/src/types.ts +86 -1
  248. package/src/utils/__tests__/dateVariable.test.ts +101 -0
  249. package/src/utils/__tests__/params-resolvers.test.ts +40 -0
  250. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +7 -0
  251. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
  252. package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
  253. package/src/utils/__tests__/runjsValue.test.ts +44 -0
  254. package/src/utils/__tests__/safeGlobals.test.ts +57 -2
  255. package/src/utils/__tests__/utils.test.ts +157 -0
  256. package/src/utils/associationObjectVariable.ts +2 -2
  257. package/src/utils/createCollectionContextMeta.ts +1 -0
  258. package/src/utils/createEphemeralContext.ts +5 -4
  259. package/src/utils/dateVariable.ts +397 -0
  260. package/src/utils/exceptions.ts +11 -0
  261. package/src/utils/index.ts +38 -3
  262. package/src/utils/params-resolvers.ts +23 -9
  263. package/src/utils/parsePathnameToViewParams.ts +2 -2
  264. package/src/utils/resolveModuleUrl.ts +91 -0
  265. package/src/utils/resolveRunJSObjectValues.ts +46 -0
  266. package/src/utils/runjsModuleLoader.ts +553 -0
  267. package/src/utils/runjsTemplateCompat.ts +828 -0
  268. package/src/utils/runjsValue.ts +287 -0
  269. package/src/utils/safeGlobals.ts +188 -17
  270. package/src/utils/schema-utils.ts +109 -1
  271. package/src/views/FlowView.tsx +11 -1
  272. package/src/views/__tests__/FlowView.usePage.test.tsx +54 -1
  273. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  274. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +44 -16
  275. package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
  276. package/src/views/createViewMeta.ts +22 -75
  277. package/src/views/index.tsx +1 -2
  278. package/src/views/runViewBeforeClose.ts +19 -0
  279. package/src/views/useDialog.tsx +34 -5
  280. package/src/views/useDrawer.tsx +33 -4
  281. package/src/views/usePage.tsx +63 -8
  282. package/src/views/usePopover.tsx +4 -1
  283. package/src/views/viewEvents.ts +55 -0
@@ -51,6 +51,10 @@ const _FlowExecutor = class _FlowExecutor {
51
51
  constructor(engine) {
52
52
  this.engine = engine;
53
53
  }
54
+ async emitModelEventIf(eventName, topic, payload) {
55
+ if (!eventName) return;
56
+ await this.engine.emitter.emitAsync(`model:event:${eventName}:${topic}`, payload);
57
+ }
54
58
  /** Cache wrapper for applyFlow cache lifecycle */
55
59
  async withApplyFlowCache(cacheKey, executor) {
56
60
  if (!cacheKey || !this.engine) return await executor();
@@ -81,7 +85,7 @@ const _FlowExecutor = class _FlowExecutor {
81
85
  /**
82
86
  * Execute a single flow on model.
83
87
  */
84
- async runFlow(model, flowKey, inputArgs, runId) {
88
+ async runFlow(model, flowKey, inputArgs, runId, eventName) {
85
89
  var _a;
86
90
  const flow = model.getFlow(flowKey);
87
91
  if (!flow) {
@@ -113,6 +117,14 @@ const _FlowExecutor = class _FlowExecutor {
113
117
  const stepDefs = eventStep ? { eventStep, ...flow.steps } : flow.steps;
114
118
  (0, import_setupRuntimeContextSteps.setupRuntimeContextSteps)(flowContext, stepDefs, model, flowKey);
115
119
  const stepsRuntime = flowContext.steps;
120
+ const flowEventBasePayload = {
121
+ uid: model.uid,
122
+ model,
123
+ runId: flowContext.runId,
124
+ inputArgs,
125
+ flowKey
126
+ };
127
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:start`, flowEventBasePayload);
116
128
  for (const [stepKey, step] of Object.entries(stepDefs)) {
117
129
  let handler;
118
130
  let combinedParams = {};
@@ -163,20 +175,58 @@ const _FlowExecutor = class _FlowExecutor {
163
175
  );
164
176
  continue;
165
177
  }
178
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:step:${stepKey}:start`, {
179
+ ...flowEventBasePayload,
180
+ stepKey
181
+ });
166
182
  const currentStepResult = handler(runtimeCtx, combinedParams);
167
183
  const isAwait = step.isAwait !== false;
168
184
  lastResult = isAwait ? await currentStepResult : currentStepResult;
169
185
  stepResults[stepKey] = lastResult;
170
186
  stepsRuntime[stepKey].result = stepResults[stepKey];
187
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:step:${stepKey}:end`, {
188
+ ...flowEventBasePayload,
189
+ result: lastResult,
190
+ stepKey
191
+ });
171
192
  } catch (error) {
193
+ if (!(error instanceof import_utils.FlowExitException) && !(error instanceof import_exceptions.FlowExitAllException)) {
194
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:step:${stepKey}:error`, {
195
+ ...flowEventBasePayload,
196
+ error,
197
+ stepKey
198
+ });
199
+ }
172
200
  if (error instanceof import_utils.FlowExitException) {
173
201
  flowContext.logger.info(`[FlowEngine] ${error.message}`);
202
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:step:${stepKey}:end`, {
203
+ ...flowEventBasePayload,
204
+ stepKey
205
+ });
206
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:end`, {
207
+ ...flowEventBasePayload,
208
+ result: stepResults
209
+ });
174
210
  return Promise.resolve(stepResults);
175
211
  }
176
212
  if (error instanceof import_exceptions.FlowExitAllException) {
177
213
  flowContext.logger.info(`[FlowEngine] ${error.message}`);
214
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:step:${stepKey}:end`, {
215
+ ...flowEventBasePayload,
216
+ stepKey,
217
+ aborted: true
218
+ });
219
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:end`, {
220
+ ...flowEventBasePayload,
221
+ result: error,
222
+ aborted: true
223
+ });
178
224
  return Promise.resolve(error);
179
225
  }
226
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:error`, {
227
+ ...flowEventBasePayload,
228
+ error
229
+ });
180
230
  flowContext.logger.error(
181
231
  { err: error },
182
232
  `BaseModel.applyFlow: Error executing step '${stepKey}' in flow '${flowKey}':`
@@ -184,9 +234,12 @@ const _FlowExecutor = class _FlowExecutor {
184
234
  return Promise.reject(error);
185
235
  }
186
236
  }
237
+ await this.emitModelEventIf(eventName, `flow:${flowKey}:end`, {
238
+ ...flowEventBasePayload,
239
+ result: stepResults
240
+ });
187
241
  return Promise.resolve(stepResults);
188
242
  }
189
- // runAutoFlows 已移除:统一通过 dispatchEvent('beforeRender') + useCache 控制
190
243
  /**
191
244
  * Dispatch an event to flows bound via flow.on and execute them.
192
245
  */
@@ -198,13 +251,14 @@ const _FlowExecutor = class _FlowExecutor {
198
251
  const throwOnError = isBeforeRender;
199
252
  const runId = `${model.uid}-${eventName}-${Date.now()}`;
200
253
  const logger = model.context.logger;
254
+ const eventBasePayload = {
255
+ uid: model.uid,
256
+ model,
257
+ runId,
258
+ inputArgs
259
+ };
201
260
  try {
202
- await this.engine.emitter.emitAsync(`model:event:${eventName}:start`, {
203
- uid: model.uid,
204
- model,
205
- runId,
206
- inputArgs
207
- });
261
+ await this.emitModelEventIf(eventName, "start", eventBasePayload);
208
262
  await ((_a = model.onDispatchEventStart) == null ? void 0 : _a.call(model, eventName, options, inputArgs));
209
263
  } catch (err) {
210
264
  if (isBeforeRender && err instanceof import_utils.FlowExitException) {
@@ -226,9 +280,18 @@ const _FlowExecutor = class _FlowExecutor {
226
280
  if (typeof on === "object") return on.eventName === eventName;
227
281
  return false;
228
282
  });
283
+ const isRouterReplayClick = eventName === "click" && (inputArgs == null ? void 0 : inputArgs.triggerByRouter) === true;
284
+ const flowsToRun = isRouterReplayClick ? flows.filter((flow) => {
285
+ var _a2;
286
+ const reg = flow["flowRegistry"];
287
+ const type = (_a2 = reg == null ? void 0 : reg.constructor) == null ? void 0 : _a2._type;
288
+ return type !== "instance";
289
+ }) : flows;
290
+ const scheduledCancels = [];
229
291
  const execute = /* @__PURE__ */ __name(async () => {
292
+ let abortedByExitAll = false;
230
293
  if (sequential) {
231
- const flowsWithIndex = flows.map((f, i) => ({ f, i }));
294
+ const flowsWithIndex = flowsToRun.map((f, i) => ({ f, i }));
232
295
  const ordered = flowsWithIndex.slice().sort((a, b) => {
233
296
  var _a2, _b2;
234
297
  const regA = a.f["flowRegistry"];
@@ -244,18 +307,110 @@ const _FlowExecutor = class _FlowExecutor {
244
307
  return a.i - b.i;
245
308
  }).map((x) => x.f);
246
309
  const results2 = [];
310
+ const staticFlowsByKey = new Map(
311
+ ordered.filter((f) => {
312
+ var _a2;
313
+ const reg = f["flowRegistry"];
314
+ const type = (_a2 = reg == null ? void 0 : reg.constructor) == null ? void 0 : _a2._type;
315
+ return type !== "instance";
316
+ }).map((f) => [f.key, f])
317
+ );
318
+ const scheduled = /* @__PURE__ */ new Set();
319
+ const scheduleGroups = /* @__PURE__ */ new Map();
320
+ ordered.forEach((flow, indexInOrdered) => {
321
+ var _a2;
322
+ const on = flow.on;
323
+ const onObj = typeof on === "object" ? on : void 0;
324
+ if (!onObj) return;
325
+ const phase = onObj.phase;
326
+ const flowKey = onObj.flowKey;
327
+ const stepKey = onObj.stepKey;
328
+ if (!phase || phase === "beforeAllFlows") return;
329
+ let whenKey = null;
330
+ if (phase === "afterAllFlows") {
331
+ whenKey = `event:${eventName}:end`;
332
+ } else if (phase === "beforeFlow" || phase === "afterFlow") {
333
+ if (!flowKey) {
334
+ whenKey = `event:${eventName}:end`;
335
+ } else {
336
+ const anchorFlow = staticFlowsByKey.get(String(flowKey));
337
+ if (anchorFlow) {
338
+ const anchorPhase = phase === "beforeFlow" ? "start" : "end";
339
+ whenKey = `event:${eventName}:flow:${String(flowKey)}:${anchorPhase}`;
340
+ } else {
341
+ whenKey = `event:${eventName}:end`;
342
+ }
343
+ }
344
+ } else if (phase === "beforeStep" || phase === "afterStep") {
345
+ if (!flowKey || !stepKey) {
346
+ whenKey = `event:${eventName}:end`;
347
+ } else {
348
+ const anchorFlow = staticFlowsByKey.get(String(flowKey));
349
+ const anchorStepExists = !!((_a2 = anchorFlow == null ? void 0 : anchorFlow.hasStep) == null ? void 0 : _a2.call(anchorFlow, String(stepKey)));
350
+ if (anchorFlow && anchorStepExists) {
351
+ const anchorPhase = phase === "beforeStep" ? "start" : "end";
352
+ whenKey = `event:${eventName}:flow:${String(flowKey)}:step:${String(stepKey)}:${anchorPhase}`;
353
+ } else {
354
+ whenKey = `event:${eventName}:end`;
355
+ }
356
+ }
357
+ } else {
358
+ return;
359
+ }
360
+ if (!whenKey) return;
361
+ const shouldSkipOnAborted = whenKey === `event:${eventName}:end` || phase === "afterFlow" || phase === "afterStep";
362
+ scheduled.add(flow.key);
363
+ const list = scheduleGroups.get(whenKey) || [];
364
+ list.push({ flow, order: indexInOrdered, shouldSkipOnAborted });
365
+ scheduleGroups.set(whenKey, list);
366
+ });
367
+ for (const [whenKey, list] of scheduleGroups.entries()) {
368
+ const sorted = list.slice().sort((a, b) => {
369
+ const sa = a.flow.sort ?? 0;
370
+ const sb = b.flow.sort ?? 0;
371
+ if (sa !== sb) return sa - sb;
372
+ return a.order - b.order;
373
+ });
374
+ for (const it of sorted) {
375
+ const when = it.shouldSkipOnAborted ? Object.assign(
376
+ (event) => event.type === whenKey && event.aborted !== true,
377
+ {
378
+ __eventType: whenKey
379
+ }
380
+ ) : whenKey;
381
+ const cancel = model.scheduleModelOperation(
382
+ model.uid,
383
+ async (m) => {
384
+ const res = await this.runFlow(m, it.flow.key, inputArgs, runId, eventName);
385
+ if (res instanceof import_exceptions.FlowExitAllException) {
386
+ throw res;
387
+ }
388
+ results2.push(res);
389
+ },
390
+ { when }
391
+ );
392
+ scheduledCancels.push(cancel);
393
+ }
394
+ }
247
395
  for (const flow of ordered) {
396
+ if (scheduled.has(flow.key)) continue;
248
397
  try {
249
398
  logger.debug(
250
399
  `BaseModel '${model.uid}' dispatching event '${eventName}' to flow '${flow.key}' (sequential).`
251
400
  );
252
- const result = await this.runFlow(model, flow.key, inputArgs, runId);
401
+ const result = await this.runFlow(model, flow.key, inputArgs, runId, eventName);
253
402
  if (result instanceof import_exceptions.FlowExitAllException) {
254
403
  logger.debug(`[FlowEngine.dispatchEvent] ${result.message}`);
404
+ abortedByExitAll = true;
255
405
  break;
256
406
  }
257
407
  results2.push(result);
258
408
  } catch (error) {
409
+ if (error instanceof import_exceptions.FlowExitAllException) {
410
+ logger.debug(`[FlowEngine.dispatchEvent] ${error.message}`);
411
+ abortedByExitAll = true;
412
+ break;
413
+ }
259
414
  logger.error(
260
415
  { err: error },
261
416
  `BaseModel.dispatchEvent: Error executing event-triggered flow '${flow.key}' for event '${eventName}' (sequential):`
@@ -263,13 +418,13 @@ const _FlowExecutor = class _FlowExecutor {
263
418
  throw error;
264
419
  }
265
420
  }
266
- return results2;
421
+ return { result: results2, abortedByExitAll };
267
422
  }
268
423
  const results = await Promise.all(
269
- flows.map(async (flow) => {
424
+ flowsToRun.map(async (flow) => {
270
425
  logger.debug(`BaseModel '${model.uid}' dispatching event '${eventName}' to flow '${flow.key}'.`);
271
426
  try {
272
- return await this.runFlow(model, flow.key, inputArgs, runId);
427
+ return await this.runFlow(model, flow.key, inputArgs, runId, eventName);
273
428
  } catch (error) {
274
429
  logger.error(
275
430
  { err: error },
@@ -280,7 +435,11 @@ const _FlowExecutor = class _FlowExecutor {
280
435
  }
281
436
  })
282
437
  );
283
- return results.filter((x) => x !== void 0);
438
+ const filteredResults = results.filter((x) => x !== void 0);
439
+ if (filteredResults.some((x) => x instanceof import_exceptions.FlowExitAllException)) {
440
+ abortedByExitAll = true;
441
+ }
442
+ return { result: filteredResults, abortedByExitAll };
284
443
  }, "execute");
285
444
  const argsKey = useCache ? JSON.stringify(inputArgs ?? {}) : "";
286
445
  const cacheKey = useCache ? import_flowEngine.FlowEngine.generateApplyFlowCacheKey(
@@ -289,19 +448,23 @@ const _FlowExecutor = class _FlowExecutor {
289
448
  model.uid
290
449
  ) : null;
291
450
  try {
292
- const result = await this.withApplyFlowCache(cacheKey, execute);
451
+ const { result, abortedByExitAll } = await this.withApplyFlowCache(cacheKey, execute);
293
452
  try {
294
453
  await ((_c = model.onDispatchEventEnd) == null ? void 0 : _c.call(model, eventName, options, inputArgs, result));
295
454
  } catch (hookErr) {
296
455
  logger.error({ err: hookErr }, `BaseModel.dispatchEvent: End hook error for event '${eventName}'`);
297
456
  }
298
- await this.engine.emitter.emitAsync(`model:event:${eventName}:end`, {
299
- uid: model.uid,
300
- model,
301
- runId,
302
- inputArgs,
303
- result
457
+ await this.emitModelEventIf(eventName, "end", {
458
+ ...eventBasePayload,
459
+ result,
460
+ ...abortedByExitAll ? { aborted: true } : {}
304
461
  });
462
+ if (result && typeof result === "object") {
463
+ Object.defineProperty(result, "__abortedByExitAll", {
464
+ value: abortedByExitAll,
465
+ configurable: true
466
+ });
467
+ }
305
468
  return result;
306
469
  } catch (error) {
307
470
  try {
@@ -312,14 +475,15 @@ const _FlowExecutor = class _FlowExecutor {
312
475
  { err: error },
313
476
  `BaseModel.dispatchEvent: Error executing event '${eventName}' for model '${model.uid}':`
314
477
  );
315
- await this.engine.emitter.emitAsync(`model:event:${eventName}:error`, {
316
- uid: model.uid,
317
- model,
318
- runId,
319
- inputArgs,
478
+ await this.emitModelEventIf(eventName, "error", {
479
+ ...eventBasePayload,
320
480
  error
321
481
  });
322
482
  if (throwOnError) throw error;
483
+ } finally {
484
+ for (const cancel of scheduledCancels) {
485
+ cancel();
486
+ }
323
487
  }
324
488
  }
325
489
  };