@nocobase/flow-engine 2.0.0-alpha.4 → 2.0.0-alpha.41

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 (466) hide show
  1. package/lib/BlockScopedFlowEngine.d.ts +23 -0
  2. package/lib/BlockScopedFlowEngine.js +90 -0
  3. package/lib/FlowContextProvider.d.ts +2 -2
  4. package/lib/FlowContextProvider.js +3 -3
  5. package/lib/FlowDefinition.d.ts +4 -2
  6. package/lib/JSRunner.js +3 -0
  7. package/lib/ViewScopedFlowEngine.d.ts +1 -1
  8. package/lib/ViewScopedFlowEngine.js +12 -0
  9. package/lib/acl/Acl.d.ts +1 -0
  10. package/lib/acl/Acl.js +11 -0
  11. package/lib/components/FieldModelRenderer.js +14 -6
  12. package/lib/components/FieldSkeleton.d.ts +10 -0
  13. package/lib/components/FieldSkeleton.js +64 -0
  14. package/lib/components/FlowContextSelector.js +7 -2
  15. package/lib/components/FlowModelRenderer.d.ts +3 -6
  16. package/lib/components/FlowModelRenderer.js +16 -47
  17. package/lib/components/FormItem.js +5 -1
  18. package/lib/components/MobilePopup.d.ts +20 -0
  19. package/lib/components/MobilePopup.js +102 -0
  20. package/lib/components/MobilePopup.style.d.ts +17 -0
  21. package/lib/components/MobilePopup.style.js +186 -0
  22. package/lib/components/index.d.ts +1 -0
  23. package/lib/components/index.js +3 -1
  24. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
  25. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
  26. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
  27. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
  28. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +35 -6
  29. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
  30. package/lib/components/variables/VariableInput.js +19 -5
  31. package/lib/components/variables/VariableTag.js +43 -2
  32. package/lib/components/variables/types.d.ts +2 -0
  33. package/lib/data-source/index.d.ts +15 -4
  34. package/lib/data-source/index.js +42 -13
  35. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  36. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  37. package/lib/emitter.d.ts +6 -0
  38. package/lib/emitter.js +12 -0
  39. package/lib/executor/FlowExecutor.d.ts +4 -5
  40. package/lib/executor/FlowExecutor.js +168 -99
  41. package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
  42. package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
  43. package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
  44. package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
  45. package/lib/flowContext.d.ts +37 -5
  46. package/lib/flowContext.js +224 -87
  47. package/lib/flowEngine.d.ts +24 -1
  48. package/lib/flowEngine.js +81 -8
  49. package/lib/flowSettings.d.ts +2 -1
  50. package/lib/flowSettings.js +16 -8
  51. package/lib/hooks/useApplyAutoFlows.js +2 -1
  52. package/lib/index.d.ts +7 -1
  53. package/lib/index.js +32 -3
  54. package/lib/locale/en-US.json +4 -2
  55. package/lib/locale/index.d.ts +4 -0
  56. package/lib/locale/zh-CN.json +4 -2
  57. package/lib/models/CollectionFieldModel.d.ts +3 -0
  58. package/lib/models/CollectionFieldModel.js +52 -6
  59. package/lib/models/flowModel.d.ts +30 -29
  60. package/lib/models/flowModel.js +153 -100
  61. package/lib/models/forkFlowModel.d.ts +8 -4
  62. package/lib/models/forkFlowModel.js +38 -8
  63. package/lib/provider.d.ts +3 -1
  64. package/lib/provider.js +7 -5
  65. package/lib/resources/multiRecordResource.js +25 -1
  66. package/lib/resources/singleRecordResource.js +19 -1
  67. package/lib/resources/sqlResource.d.ts +1 -0
  68. package/lib/resources/sqlResource.js +20 -24
  69. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  70. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  71. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  72. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  73. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  74. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  75. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  76. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  77. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  78. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  79. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  80. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  81. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  82. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  83. package/lib/runjs-context/contexts/base.d.ts +9 -0
  84. package/lib/runjs-context/contexts/base.js +205 -0
  85. package/lib/runjs-context/helpers.d.ts +5 -2
  86. package/lib/runjs-context/helpers.js +36 -27
  87. package/lib/runjs-context/registry.d.ts +7 -4
  88. package/lib/runjs-context/registry.js +10 -42
  89. package/lib/runjs-context/setup.d.ts +9 -0
  90. package/lib/runjs-context/setup.js +82 -0
  91. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  92. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  93. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  94. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  95. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  96. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  97. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  98. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  99. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  100. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  101. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  102. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  103. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  104. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  105. package/lib/runjs-context/snippets/index.d.ts +14 -3
  106. package/lib/runjs-context/snippets/index.js +162 -40
  107. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  109. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  111. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  113. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  114. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  115. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  116. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  117. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  118. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  119. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  120. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  121. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  122. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  123. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  124. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  125. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  126. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  127. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  128. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  129. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  130. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  131. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  132. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  133. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  134. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  135. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  136. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  137. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  138. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  139. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  140. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  141. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  142. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  143. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  144. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  145. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  146. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  147. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  148. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  149. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  150. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  151. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  152. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  153. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  154. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  155. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  156. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  157. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  158. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  159. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  160. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  161. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  162. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  163. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  164. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  165. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  166. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  167. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  168. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  169. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  170. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  171. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  172. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  173. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  174. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  175. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  176. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  177. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  178. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  179. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  180. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  181. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  182. package/lib/runjs-context/snippets/types.d.ts +9 -1
  183. package/lib/scheduler/ModelOperationScheduler.d.ts +51 -0
  184. package/lib/scheduler/ModelOperationScheduler.js +262 -0
  185. package/lib/types.d.ts +28 -3
  186. package/lib/types.js +4 -3
  187. package/lib/utils/associationObjectVariable.d.ts +32 -0
  188. package/lib/utils/associationObjectVariable.js +157 -0
  189. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  190. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  191. package/lib/utils/createEphemeralContext.d.ts +13 -0
  192. package/lib/utils/createEphemeralContext.js +140 -0
  193. package/lib/utils/flows.d.ts +10 -0
  194. package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → utils/flows.js} +21 -15
  195. package/lib/utils/index.d.ts +7 -2
  196. package/lib/utils/index.js +21 -2
  197. package/lib/utils/jsxTransform.d.ts +15 -0
  198. package/lib/utils/jsxTransform.js +68 -0
  199. package/lib/utils/params-resolvers.js +3 -3
  200. package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
  201. package/lib/utils/parsePathnameToViewParams.js +41 -5
  202. package/lib/utils/pruneFilter.d.ts +21 -0
  203. package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
  204. package/lib/utils/safeGlobals.d.ts +5 -3
  205. package/lib/utils/safeGlobals.js +40 -0
  206. package/lib/utils/schema-utils.js +2 -2
  207. package/lib/utils/serverContextParams.d.ts +1 -0
  208. package/lib/utils/translation.d.ts +4 -1
  209. package/lib/utils/translation.js +6 -2
  210. package/lib/utils/variablesParams.d.ts +22 -5
  211. package/lib/utils/variablesParams.js +132 -36
  212. package/lib/views/DrawerComponent.js +21 -2
  213. package/lib/views/PageComponent.js +2 -1
  214. package/lib/views/ViewNavigation.d.ts +3 -9
  215. package/lib/views/ViewNavigation.js +16 -2
  216. package/lib/views/createViewMeta.d.ts +29 -1
  217. package/lib/views/createViewMeta.js +338 -72
  218. package/lib/views/index.d.ts +1 -0
  219. package/lib/views/index.js +3 -0
  220. package/lib/views/useDialog.d.ts +9 -8
  221. package/lib/views/useDialog.js +19 -14
  222. package/lib/views/useDrawer.d.ts +9 -8
  223. package/lib/views/useDrawer.js +54 -35
  224. package/lib/views/usePage.d.ts +9 -8
  225. package/lib/views/usePage.js +20 -14
  226. package/package.json +6 -3
  227. package/src/BlockScopedFlowEngine.ts +86 -0
  228. package/src/FlowContextProvider.tsx +4 -2
  229. package/src/JSRunner.ts +3 -0
  230. package/src/ViewScopedFlowEngine.ts +15 -1
  231. package/src/__tests__/JSRunner.test.ts +62 -53
  232. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  233. package/src/__tests__/createViewMeta.popup.test.ts +132 -0
  234. package/src/__tests__/flow-engine.test.ts +3 -0
  235. package/src/__tests__/flowContext.test.ts +52 -0
  236. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  237. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  238. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  239. package/src/__tests__/flowSettings.open.test.tsx +2 -0
  240. package/src/__tests__/flowSettings.test.ts +2 -0
  241. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  242. package/src/__tests__/modelOperationScheduler.test.ts +346 -0
  243. package/src/__tests__/objectVariable.test.ts +464 -0
  244. package/src/__tests__/runjsContext.test.ts +216 -35
  245. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  246. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  247. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  248. package/src/__tests__/runjsLocales.test.ts +36 -0
  249. package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
  250. package/src/__tests__/runjsSnippets.test.ts +140 -0
  251. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  252. package/src/acl/Acl.tsx +14 -0
  253. package/src/acl/__tests__/Acl.test.tsx +43 -0
  254. package/src/components/DynamicFlowsEditor.tsx +3 -4
  255. package/src/components/FieldModelRenderer.tsx +20 -7
  256. package/src/components/FieldSkeleton.tsx +27 -0
  257. package/src/components/FlowContextSelector.tsx +6 -2
  258. package/src/components/FlowModelRenderer.tsx +33 -81
  259. package/src/components/FormItem.tsx +8 -1
  260. package/src/components/MobilePopup.style.ts +220 -0
  261. package/src/components/MobilePopup.tsx +86 -0
  262. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
  263. package/src/components/index.ts +1 -0
  264. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
  265. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
  266. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
  267. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +39 -10
  268. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  269. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +425 -0
  270. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
  271. package/src/components/variables/VariableInput.tsx +25 -5
  272. package/src/components/variables/VariableTag.tsx +54 -2
  273. package/src/components/variables/types.ts +2 -0
  274. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  275. package/src/data-source/index.ts +42 -11
  276. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  277. package/src/emitter.ts +14 -0
  278. package/src/executor/FlowExecutor.ts +213 -119
  279. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  280. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  281. package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
  282. package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
  283. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
  284. package/src/flowContext.ts +303 -104
  285. package/src/flowEngine.ts +96 -6
  286. package/src/flowSettings.ts +12 -4
  287. package/src/hooks/useApplyAutoFlows.ts +3 -1
  288. package/src/index.ts +12 -1
  289. package/src/locale/en-US.json +4 -2
  290. package/src/locale/zh-CN.json +4 -2
  291. package/src/models/CollectionFieldModel.tsx +60 -8
  292. package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
  293. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
  294. package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
  295. package/src/models/__tests__/flowModel.test.ts +234 -111
  296. package/src/models/__tests__/forkFlowModel.test.ts +40 -7
  297. package/src/models/flowModel.tsx +197 -132
  298. package/src/models/forkFlowModel.ts +48 -8
  299. package/src/provider.tsx +10 -7
  300. package/src/resources/multiRecordResource.ts +28 -1
  301. package/src/resources/singleRecordResource.ts +19 -1
  302. package/src/resources/sqlResource.ts +20 -25
  303. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  304. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  305. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  306. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  307. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  308. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  309. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  310. package/src/runjs-context/contexts/base.ts +196 -0
  311. package/src/runjs-context/helpers.ts +32 -30
  312. package/src/runjs-context/registry.ts +16 -47
  313. package/src/runjs-context/setup.ts +51 -0
  314. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  315. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  316. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  317. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  318. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  319. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  320. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  321. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  322. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  323. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  324. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  325. package/src/runjs-context/snippets/index.ts +178 -39
  326. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  327. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  328. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  329. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  330. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  331. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  332. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  333. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  334. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  335. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  336. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  337. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  338. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  339. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  340. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  341. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  342. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  343. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  344. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  345. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  346. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  347. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  348. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  349. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  350. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  351. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  352. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  353. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  354. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  355. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  356. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  357. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  358. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  359. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  360. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  361. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  362. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  363. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  364. package/src/runjs-context/snippets/types.ts +5 -1
  365. package/src/scheduler/ModelOperationScheduler.ts +304 -0
  366. package/src/types.ts +34 -0
  367. package/src/utils/__tests__/flows.test.ts +65 -0
  368. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  369. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
  370. package/src/utils/__tests__/pruneFilter.test.ts +38 -0
  371. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  372. package/src/utils/__tests__/variablesParams.test.ts +63 -0
  373. package/src/utils/associationObjectVariable.ts +180 -0
  374. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  375. package/src/utils/createEphemeralContext.ts +142 -0
  376. package/src/utils/flows.ts +23 -0
  377. package/src/utils/index.ts +11 -2
  378. package/src/utils/jsxTransform.ts +39 -0
  379. package/src/utils/params-resolvers.ts +2 -2
  380. package/src/utils/parsePathnameToViewParams.ts +50 -6
  381. package/src/utils/pruneFilter.ts +41 -0
  382. package/src/utils/safeGlobals.ts +49 -3
  383. package/src/utils/schema-utils.ts +1 -1
  384. package/src/utils/serverContextParams.ts +1 -0
  385. package/src/utils/translation.ts +7 -2
  386. package/src/utils/variablesParams.ts +156 -38
  387. package/src/views/DrawerComponent.tsx +21 -2
  388. package/src/views/PageComponent.tsx +1 -1
  389. package/src/views/ViewNavigation.ts +20 -12
  390. package/src/views/__tests__/ViewNavigation.test.ts +10 -0
  391. package/src/views/createViewMeta.ts +393 -70
  392. package/src/views/index.tsx +1 -0
  393. package/src/views/useDialog.tsx +24 -18
  394. package/src/views/useDrawer.tsx +74 -45
  395. package/src/views/usePage.tsx +26 -17
  396. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  397. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  398. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  399. package/lib/runjs-context/index.d.ts +0 -19
  400. package/lib/runjs-context/index.js +0 -57
  401. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  402. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  403. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  404. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  405. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  406. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
  407. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  408. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  409. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  410. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  411. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  412. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  413. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  414. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  415. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  416. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  417. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  418. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  419. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  420. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  421. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +0 -46
  422. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  423. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  424. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  425. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  426. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  427. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  428. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  429. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  430. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  431. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  432. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  433. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  434. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  435. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  436. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  437. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  438. package/src/runjs-context/index.ts +0 -20
  439. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  440. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  441. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  442. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  443. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  444. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  445. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  446. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  447. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  448. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  449. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  450. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  451. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  452. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  453. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  454. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  455. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  456. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  457. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  458. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  459. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  460. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  461. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  462. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  463. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  464. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  465. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  466. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -7,18 +7,17 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- import { autorun, observable, reaction, reactive } from '@nocobase/flow-engine';
11
- import { APIClient } from '@nocobase/sdk';
10
+ import { reaction } from '@nocobase/flow-engine';
12
11
  import { render, waitFor } from '@testing-library/react';
13
12
  import React from 'react';
14
13
  import { vi } from 'vitest';
15
14
  import { FlowModelRenderer } from '../../components/FlowModelRenderer';
15
+ import { FlowEngineProvider } from '../../provider';
16
16
  import { FlowEngine } from '../../flowEngine';
17
- import type { DefaultStructure, FlowDefinitionOptions, FlowModelOptions, ModelConstructor } from '../../types';
17
+ import type { DefaultStructure, FlowDefinitionOptions, FlowModelOptions } from '../../types';
18
18
  import { FlowExitException } from '../../utils';
19
19
  import { FlowExitAllException } from '../../utils/exceptions';
20
- import { defineFlow, FlowModel, ModelRenderMode } from '../flowModel';
21
- import { ForkFlowModel } from '../forkFlowModel';
20
+ import { FlowModel, ModelRenderMode } from '../flowModel';
22
21
 
23
22
  // 全局处理测试中的未处理 Promise rejection
24
23
  const originalUnhandledRejection = process.listeners('unhandledRejection');
@@ -392,7 +391,7 @@ describe('FlowModel', () => {
392
391
  TestFlowModel.registerFlow(exitFlow2);
393
392
  const loggerSpy = vi.spyOn(model.context.logger, 'info').mockImplementation(() => {});
394
393
 
395
- await model.applyAutoFlows();
394
+ await model.dispatchEvent('beforeRender');
396
395
 
397
396
  expect(exitFlow.steps.step2.handler).not.toHaveBeenCalled();
398
397
  expect(exitFlow2.steps.step2.handler).toHaveBeenCalled();
@@ -430,7 +429,7 @@ describe('FlowModel', () => {
430
429
  TestFlowModel.registerFlow(exitFlow2);
431
430
  const loggerSpy = vi.spyOn(model.context.logger, 'info').mockImplementation(() => {});
432
431
 
433
- await model.applyAutoFlows();
432
+ await model.dispatchEvent('beforeRender');
434
433
 
435
434
  expect(exitFlow.steps.step2.handler).not.toHaveBeenCalled();
436
435
  expect(exitFlow2.steps.step2.handler).not.toHaveBeenCalled();
@@ -530,7 +529,7 @@ describe('FlowModel', () => {
530
529
  });
531
530
  });
532
531
 
533
- describe('applyAutoFlows', () => {
532
+ describe('beforeRender flows', () => {
534
533
  test('should execute all auto flows', async () => {
535
534
  const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1', sort: 1 };
536
535
  const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2', sort: 2 };
@@ -540,7 +539,7 @@ describe('FlowModel', () => {
540
539
  TestFlowModel.registerFlow(autoFlow2);
541
540
  TestFlowModel.registerFlow(manualFlow);
542
541
 
543
- const results = await model.applyAutoFlows();
542
+ const results = await model.dispatchEvent('beforeRender');
544
543
 
545
544
  expect(results).toHaveLength(2);
546
545
  expect(autoFlow1.steps.autoStep.handler).toHaveBeenCalled();
@@ -594,13 +593,13 @@ describe('FlowModel', () => {
594
593
  TestFlowModel.registerFlow(autoFlow2);
595
594
  TestFlowModel.registerFlow(autoFlow3);
596
595
 
597
- await model.applyAutoFlows();
596
+ await model.dispatchEvent('beforeRender');
598
597
 
599
598
  expect(executionOrder).toEqual(['auto2', 'auto3', 'auto1']);
600
599
  });
601
600
 
602
601
  test('should no results when no auto flows found', async () => {
603
- const results = await model.applyAutoFlows();
602
+ const results = await model.dispatchEvent('beforeRender');
604
603
 
605
604
  expect(results).toEqual([]);
606
605
  // Note: Log output may be captured in stderr, not console.log
@@ -617,16 +616,14 @@ describe('FlowModel', () => {
617
616
  afterHookSpy = vi.fn();
618
617
  errorHookSpy = vi.fn();
619
618
  TestFlowModelWithHooks = class extends TestFlowModel {
620
- async onBeforeAutoFlows(inputArgs?: Record<string, any>) {
621
- beforeHookSpy(inputArgs);
619
+ async onDispatchEventStart(eventName: string, _opts?: any, inputArgs?: Record<string, any>) {
620
+ if (eventName === 'beforeRender') beforeHookSpy(inputArgs);
622
621
  }
623
-
624
- async onAfterAutoFlows(results: any[], inputArgs?: Record<string, any>) {
625
- afterHookSpy(results, inputArgs);
622
+ async onDispatchEventEnd(eventName: string, _opts?: any, inputArgs?: Record<string, any>, results?: any[]) {
623
+ if (eventName === 'beforeRender') afterHookSpy(results, inputArgs);
626
624
  }
627
-
628
- async onAutoFlowsError(error: Error, inputArgs?: Record<string, any>) {
629
- errorHookSpy(error, inputArgs);
625
+ async onDispatchEventError(eventName: string, _opts?: any, inputArgs?: Record<string, any>, error?: Error) {
626
+ if (eventName === 'beforeRender') errorHookSpy(error, inputArgs);
630
627
  }
631
628
  };
632
629
  });
@@ -638,7 +635,7 @@ describe('FlowModel', () => {
638
635
  const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
639
636
  const inputArgs = { test: 'value' };
640
637
 
641
- const results = await modelWithHooks.applyAutoFlows(inputArgs);
638
+ const results = await modelWithHooks.dispatchEvent('beforeRender', inputArgs);
642
639
 
643
640
  // Verify hooks were called
644
641
  expect(beforeHookSpy).toHaveBeenCalledTimes(1);
@@ -654,22 +651,22 @@ describe('FlowModel', () => {
654
651
  );
655
652
  });
656
653
 
657
- test('should allow onBeforeAutoFlows to terminate flow via ctx.exit()', async () => {
654
+ test("should allow onDispatchEventStart('beforeRender') to terminate flow via ctx.exit()", async () => {
658
655
  const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1' };
659
656
  const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2' };
660
657
 
661
658
  const TestFlowModelWithExitHooks = class extends TestFlowModel {
662
- async onBeforeAutoFlows(inputArgs?: Record<string, any>) {
663
- beforeHookSpy(inputArgs);
664
- throw new FlowExitException('autoFlows', this.uid);
659
+ async onDispatchEventStart(eventName: string, _opts?: any, inputArgs?: Record<string, any>) {
660
+ if (eventName === 'beforeRender') {
661
+ beforeHookSpy(inputArgs);
662
+ throw new FlowExitException('beforeRender', this.uid);
663
+ }
665
664
  }
666
-
667
- async onAfterAutoFlows(results: any[], inputArgs?: Record<string, any>) {
668
- afterHookSpy(results, inputArgs);
665
+ async onDispatchEventEnd(eventName: string, _o?: any, _i?: any, _r?: any[]) {
666
+ if (eventName === 'beforeRender') afterHookSpy(_r, _i);
669
667
  }
670
-
671
- async onAutoFlowsError(error: Error, inputArgs?: Record<string, any>) {
672
- errorHookSpy(error, inputArgs);
668
+ async onDispatchEventError(eventName: string, _o?: any, i?: any, e?: Error) {
669
+ if (eventName === 'beforeRender') errorHookSpy(e, i);
673
670
  }
674
671
  };
675
672
 
@@ -678,9 +675,9 @@ describe('FlowModel', () => {
678
675
  TestFlowModelWithExitHooks.registerFlow(autoFlow2);
679
676
 
680
677
  const modelWithHooks = new TestFlowModelWithExitHooks(modelOptions);
681
- const results = await modelWithHooks.applyAutoFlows();
678
+ const results = await modelWithHooks.dispatchEvent('beforeRender');
682
679
 
683
- // Should have called onBeforeAutoFlows but not onAfterAutoFlows
680
+ // Should have called onDispatchEventStart but not onDispatchEventEnd
684
681
  expect(beforeHookSpy).toHaveBeenCalledTimes(1);
685
682
  expect(afterHookSpy).not.toHaveBeenCalled();
686
683
  expect(errorHookSpy).not.toHaveBeenCalled();
@@ -688,12 +685,12 @@ describe('FlowModel', () => {
688
685
  // Should return empty results since flow was terminated early
689
686
  expect(results).toEqual([]);
690
687
 
691
- // Auto flows should not have been executed
688
+ // flows should not have been executed
692
689
  expect(autoFlow1.steps.autoStep.handler).not.toHaveBeenCalled();
693
690
  expect(autoFlow2.steps.autoStep.handler).not.toHaveBeenCalled();
694
691
  });
695
692
 
696
- test('should call onAutoFlowsError when flow execution fails', async () => {
693
+ test("should call onDispatchEventError('beforeRender') when flow execution fails", async () => {
697
694
  const errorFlow = {
698
695
  key: 'errorFlow',
699
696
 
@@ -708,11 +705,8 @@ describe('FlowModel', () => {
708
705
  TestFlowModelWithHooks.registerFlow(errorFlow);
709
706
 
710
707
  const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
711
-
712
- // 测试错误处理钩子功能
713
- await expect(modelWithHooks.applyAutoFlows()).rejects.toThrow('Test error');
714
-
715
- // Verify hooks were called
708
+ await expect(modelWithHooks.dispatchEvent('beforeRender')).rejects.toThrow('Test error');
709
+ // Verify hooks were called (error path)
716
710
  expect(beforeHookSpy).toHaveBeenCalledTimes(1);
717
711
  expect(afterHookSpy).not.toHaveBeenCalled();
718
712
  expect(errorHookSpy).toHaveBeenCalledTimes(1);
@@ -726,14 +720,14 @@ describe('FlowModel', () => {
726
720
  );
727
721
  });
728
722
 
729
- test('should provide access to step results in onAfterAutoFlows', async () => {
723
+ test('should provide access to step results in onDispatchEventEnd(beforeRender)', async () => {
730
724
  const autoFlow1 = { ...createAutoFlowDefinition(), key: 'auto1' };
731
725
  const autoFlow2 = { ...createAutoFlowDefinition(), key: 'auto2' };
732
726
  TestFlowModelWithHooks.registerFlow(autoFlow1);
733
727
  TestFlowModelWithHooks.registerFlow(autoFlow2);
734
728
 
735
729
  const modelWithHooks = new TestFlowModelWithHooks(modelOptions);
736
- await modelWithHooks.applyAutoFlows();
730
+ await modelWithHooks.dispatchEvent('beforeRender');
737
731
 
738
732
  expect(afterHookSpy).toHaveBeenCalledTimes(1);
739
733
 
@@ -777,6 +771,82 @@ describe('FlowModel', () => {
777
771
  }
778
772
  });
779
773
 
774
+ test('getFlows includes beforeRender and no-on flows; excludes manual and other events', async () => {
775
+ const TestM = class extends FlowModel {};
776
+ const beforeHandler = vi.fn();
777
+ const noOnHandler = vi.fn();
778
+ const manualHandler = vi.fn();
779
+
780
+ TestM.registerFlow({ key: 'beforeA', on: 'beforeRender', sort: 2, steps: { s: { handler: beforeHandler } } });
781
+ TestM.registerFlow({ key: 'noOnB', sort: 1, steps: { s: { handler: noOnHandler } } });
782
+ TestM.registerFlow({ key: 'manualSkip', manual: true, steps: { s: { handler: manualHandler } } });
783
+ TestM.registerFlow({ key: 'otherEvent', on: 'click', steps: { s: { handler: vi.fn() } } });
784
+
785
+ const m = new TestM(modelOptions);
786
+ const autoKeys = m.getEventFlows('beforeRender').map((f) => f.key);
787
+
788
+ // sort 按 1,2 排序:noOnB -> beforeA
789
+ expect(autoKeys).toEqual(['noOnB', 'beforeA']);
790
+
791
+ // beforeRender 会运行两者
792
+ await m.dispatchEvent('beforeRender');
793
+ expect(beforeHandler).toHaveBeenCalledTimes(1);
794
+ expect(noOnHandler).toHaveBeenCalledTimes(1);
795
+ expect(manualHandler).not.toHaveBeenCalled();
796
+ });
797
+
798
+ test('beforeRender executes in sort order mixing no-on and beforeRender', async () => {
799
+ const TestM = class extends FlowModel {};
800
+ const calls: string[] = [];
801
+ TestM.registerFlow({ key: 'noOn1', sort: 1, steps: { s: { handler: () => calls.push('noOn1') } } });
802
+ TestM.registerFlow({
803
+ key: 'before2',
804
+ on: 'beforeRender',
805
+ sort: 2,
806
+ steps: { s: { handler: () => calls.push('before2') } },
807
+ });
808
+ TestM.registerFlow({ key: 'noOn3', sort: 3, steps: { s: { handler: () => calls.push('noOn3') } } });
809
+
810
+ const m = new TestM(modelOptions);
811
+ await m.dispatchEvent('beforeRender');
812
+ expect(calls).toEqual(['noOn1', 'before2', 'noOn3']);
813
+ });
814
+
815
+ test("model.dispatchEvent('beforeRender') uses cache keyed by eventName", async () => {
816
+ const TestM = class extends FlowModel {};
817
+ const handler = vi.fn();
818
+ TestM.registerFlow({ key: 'autoA', steps: { s: { handler } } });
819
+
820
+ const m = new TestM(modelOptions);
821
+ await m.dispatchEvent('beforeRender');
822
+ await m.dispatchEvent('beforeRender');
823
+ expect(handler).toHaveBeenCalledTimes(1);
824
+ });
825
+
826
+ test('invalidFlowCache should clear specific event cache', async () => {
827
+ const TestM = class extends FlowModel {};
828
+ const h1 = vi.fn();
829
+ const h2 = vi.fn();
830
+ TestM.registerFlow({ key: 'onFoo', on: 'foo', steps: { s: { handler: h1 } } });
831
+ TestM.registerFlow({ key: 'onBar', on: 'bar', steps: { s: { handler: h2 } } });
832
+
833
+ const m = new TestM(modelOptions);
834
+ await m.dispatchEvent('foo', {}, { useCache: true });
835
+ await m.dispatchEvent('bar', {}, { useCache: true });
836
+
837
+ // cached
838
+ await m.dispatchEvent('foo', {}, { useCache: true });
839
+ await m.dispatchEvent('bar', {}, { useCache: true });
840
+ expect(h1).toHaveBeenCalledTimes(1);
841
+ expect(h2).toHaveBeenCalledTimes(1);
842
+
843
+ // invalidate foo only
844
+ m.invalidateFlowCache('foo');
845
+ await m.dispatchEvent('foo', {}, { useCache: true });
846
+ await m.dispatchEvent('bar', {}, { useCache: true });
847
+ expect(h1).toHaveBeenCalledTimes(2);
848
+ expect(h2).toHaveBeenCalledTimes(1);
849
+ });
780
850
  test('should handle multiple flows for same event', async () => {
781
851
  const eventFlow1 = { ...createEventFlowDefinition('sharedEvent'), key: 'event1' };
782
852
  const eventFlow2 = { ...createEventFlowDefinition('sharedEvent'), key: 'event2' };
@@ -802,9 +872,13 @@ describe('FlowModel', () => {
802
872
  const _dispatchEventWithDebounceSpy = vi.spyOn(model as any, '_dispatchEventWithDebounce');
803
873
 
804
874
  // Test with debounce enabled
805
- await model.dispatchEvent('debouncedEvent', { data: 'test' }, { debounce: true });
875
+ await model.dispatchEvent('debouncedEvent', { data: 'test' }, { debounce: true, sequential: true });
806
876
 
807
- expect(_dispatchEventWithDebounceSpy).toHaveBeenCalledWith('debouncedEvent', { data: 'test' });
877
+ expect(_dispatchEventWithDebounceSpy).toHaveBeenCalledWith(
878
+ 'debouncedEvent',
879
+ { data: 'test' },
880
+ expect.objectContaining({ sequential: true }),
881
+ );
808
882
  expect(_dispatchEventSpy).not.toHaveBeenCalled();
809
883
 
810
884
  _dispatchEventSpy.mockRestore();
@@ -821,7 +895,11 @@ describe('FlowModel', () => {
821
895
  // Test with debounce disabled
822
896
  await model.dispatchEvent('normalEvent', { data: 'test' }, { debounce: false });
823
897
 
824
- expect(_dispatchEventSpy).toHaveBeenCalledWith('normalEvent', { data: 'test' });
898
+ expect(_dispatchEventSpy).toHaveBeenCalledWith(
899
+ 'normalEvent',
900
+ { data: 'test' },
901
+ expect.objectContaining({ sequential: true }),
902
+ );
825
903
  expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
826
904
 
827
905
  _dispatchEventSpy.mockRestore();
@@ -838,7 +916,11 @@ describe('FlowModel', () => {
838
916
  // Test without debounce option
839
917
  await model.dispatchEvent('defaultEvent', { data: 'test' });
840
918
 
841
- expect(_dispatchEventSpy).toHaveBeenCalledWith('defaultEvent', { data: 'test' });
919
+ expect(_dispatchEventSpy).toHaveBeenCalledWith(
920
+ 'defaultEvent',
921
+ { data: 'test' },
922
+ expect.objectContaining({ sequential: true }),
923
+ );
842
924
  expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
843
925
 
844
926
  _dispatchEventSpy.mockRestore();
@@ -855,7 +937,11 @@ describe('FlowModel', () => {
855
937
  // Test with undefined options
856
938
  await model.dispatchEvent('undefinedOptionsEvent', { data: 'test' }, undefined);
857
939
 
858
- expect(_dispatchEventSpy).toHaveBeenCalledWith('undefinedOptionsEvent', { data: 'test' });
940
+ expect(_dispatchEventSpy).toHaveBeenCalledWith(
941
+ 'undefinedOptionsEvent',
942
+ { data: 'test' },
943
+ expect.objectContaining({ sequential: true }),
944
+ );
859
945
  expect(_dispatchEventWithDebounceSpy).not.toHaveBeenCalled();
860
946
 
861
947
  _dispatchEventSpy.mockRestore();
@@ -1265,41 +1351,63 @@ describe('FlowModel', () => {
1265
1351
  });
1266
1352
  });
1267
1353
 
1268
- describe('applySubModelsAutoFlows', () => {
1354
+ describe('applySubModelsBeforeRenderFlows', () => {
1269
1355
  test('should apply auto flows to all array subModels', async () => {
1270
1356
  const child1 = new FlowModel({ uid: 'child1', flowEngine });
1271
1357
  const child2 = new FlowModel({ uid: 'child2', flowEngine });
1272
1358
 
1273
- child1.applyAutoFlows = vi.fn().mockResolvedValue([]);
1274
- child2.applyAutoFlows = vi.fn().mockResolvedValue([]);
1359
+ child1.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
1360
+ child2.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
1275
1361
 
1276
1362
  parentModel.addSubModel('children', child1);
1277
1363
  parentModel.addSubModel('children', child2);
1278
1364
 
1279
1365
  const runtimeData = { test: 'extra' };
1280
1366
 
1281
- await parentModel.applySubModelsAutoFlows('children', runtimeData);
1367
+ await parentModel.applySubModelsBeforeRenderFlows('children', runtimeData);
1282
1368
 
1283
- expect(child1.applyAutoFlows).toHaveBeenCalledWith(runtimeData);
1284
- expect(child2.applyAutoFlows).toHaveBeenCalledWith(runtimeData);
1369
+ expect(child1.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
1370
+ expect(child2.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
1285
1371
  });
1286
1372
 
1287
1373
  test('should apply auto flows to single subModel', async () => {
1288
1374
  const child = new FlowModel({ uid: 'child', flowEngine });
1289
1375
 
1290
- child.applyAutoFlows = vi.fn().mockResolvedValue([]);
1376
+ child.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
1291
1377
 
1292
1378
  parentModel.setSubModel('child', child);
1293
1379
 
1294
1380
  const runtimeData = { test: 'extra' };
1295
1381
 
1296
- await parentModel.applySubModelsAutoFlows('child', runtimeData);
1382
+ await parentModel.applySubModelsBeforeRenderFlows('child', runtimeData);
1297
1383
 
1298
- expect(child.applyAutoFlows).toHaveBeenCalledWith(runtimeData);
1384
+ expect(child.dispatchEvent).toHaveBeenCalledWith('beforeRender', runtimeData);
1299
1385
  });
1300
1386
 
1301
1387
  test('should handle empty subModels gracefully', async () => {
1302
- await expect(parentModel.applySubModelsAutoFlows('nonExistent')).resolves.not.toThrow();
1388
+ await expect(parentModel.applySubModelsBeforeRenderFlows('nonExistent')).resolves.not.toThrow();
1389
+ });
1390
+ });
1391
+
1392
+ describe('beforeRender cache invalidation on inputArgs change', () => {
1393
+ test('should rerun when inputArgs changed and reuse when equal', async () => {
1394
+ const TestM = class extends FlowModel {};
1395
+ const handler = vi.fn();
1396
+ TestM.registerFlow({ key: 'auto1', steps: { s: { handler } } });
1397
+
1398
+ const m = new TestM(modelOptions);
1399
+
1400
+ // First run with {a:1}
1401
+ await m.dispatchEvent('beforeRender', { a: 1 });
1402
+ expect(handler).toHaveBeenCalledTimes(1);
1403
+
1404
+ // Second run with same args should hit cache -> no extra handler calls
1405
+ await m.dispatchEvent('beforeRender', { a: 1 });
1406
+ expect(handler).toHaveBeenCalledTimes(1);
1407
+
1408
+ // Different args invalidate cache -> handler called again
1409
+ await m.dispatchEvent('beforeRender', { a: 2 });
1410
+ expect(handler).toHaveBeenCalledTimes(2);
1303
1411
  });
1304
1412
  });
1305
1413
 
@@ -1415,8 +1523,6 @@ describe('FlowModel', () => {
1415
1523
  const fork1 = model.createFork();
1416
1524
  const fork2 = model.createFork();
1417
1525
 
1418
- expect(fork1.forkId).toBe(0);
1419
- expect(fork2.forkId).toBe(1);
1420
1526
  expect(model.forks.size).toBe(2);
1421
1527
  expect(model.forks.has(fork1)).toBe(true);
1422
1528
  expect(model.forks.has(fork2)).toBe(true);
@@ -1435,8 +1541,6 @@ describe('FlowModel', () => {
1435
1541
  const fork2 = model.createFork({}, 'key2');
1436
1542
 
1437
1543
  expect(fork1).not.toBe(fork2);
1438
- expect(fork1.forkId).toBe(0);
1439
- expect(fork2.forkId).toBe(1);
1440
1544
  });
1441
1545
 
1442
1546
  test('should create fork with local props', () => {
@@ -1627,7 +1731,7 @@ describe('FlowModel', () => {
1627
1731
  });
1628
1732
 
1629
1733
  describe('rendering operations', () => {
1630
- test('should not pre-call render for RenderFunction mode and call exactly once on render', () => {
1734
+ test('should not pre-call render for RenderFunction mode and call exactly once on render', async () => {
1631
1735
  const renderSpy = vi.fn(() => vi.fn());
1632
1736
 
1633
1737
  class CallbackRenderModel extends FlowModel {
@@ -1645,17 +1749,20 @@ describe('FlowModel', () => {
1645
1749
  const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
1646
1750
  try {
1647
1751
  const { unmount } = render(
1648
- React.createElement(FlowModelRenderer, { model: callbackModel, skipApplyAutoFlows: true }),
1752
+ React.createElement(
1753
+ FlowEngineProvider,
1754
+ { engine: callbackModel.flowEngine },
1755
+ React.createElement(FlowModelRenderer, { model: callbackModel }),
1756
+ ),
1649
1757
  );
1650
-
1651
- expect(renderSpy).toHaveBeenCalledTimes(1);
1758
+ await waitFor(() => expect(renderSpy).toHaveBeenCalledTimes(1));
1652
1759
  unmount();
1653
1760
  } finally {
1654
1761
  warnSpy.mockRestore();
1655
1762
  }
1656
1763
  });
1657
1764
 
1658
- test('should not pre-call render for ReactElement mode and call exactly once on actual render', () => {
1765
+ test('should not pre-call render for ReactElement mode and call exactly once on actual render', async () => {
1659
1766
  const renderSpy = vi.fn(() => React.createElement('div', { 'data-testid': 'elt' }, 'Elt'));
1660
1767
 
1661
1768
  class ElementRenderModel extends FlowModel {
@@ -1670,11 +1777,15 @@ describe('FlowModel', () => {
1670
1777
  expect(renderSpy).toHaveBeenCalledTimes(0);
1671
1778
 
1672
1779
  const { getByTestId, unmount } = render(
1673
- React.createElement(FlowModelRenderer, { model: elementModel, skipApplyAutoFlows: true }),
1780
+ React.createElement(
1781
+ FlowEngineProvider,
1782
+ { engine: elementModel.flowEngine },
1783
+ React.createElement(FlowModelRenderer, { model: elementModel }),
1784
+ ),
1674
1785
  );
1675
1786
 
1676
1787
  // Render should be called exactly once during mount
1677
- expect(renderSpy).toHaveBeenCalledTimes(1);
1788
+ await waitFor(() => expect(renderSpy).toHaveBeenCalledTimes(1));
1678
1789
  expect(getByTestId('elt')).toBeTruthy();
1679
1790
 
1680
1791
  unmount();
@@ -1690,13 +1801,15 @@ describe('FlowModel', () => {
1690
1801
  expect(result.type.displayName).toBe('ReactiveWrapper(FlowModel)');
1691
1802
  });
1692
1803
 
1693
- test('should rerender with previous auto flows', async () => {
1804
+ test('should rerender triggers beforeRender without cache', async () => {
1694
1805
  const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
1695
- model.applyAutoFlows = vi.fn().mockResolvedValue([]);
1806
+ model.dispatchEvent = vi.fn().mockResolvedValue(undefined) as any;
1696
1807
 
1697
1808
  try {
1698
1809
  await expect(model.rerender()).resolves.not.toThrow();
1699
- expect(model.applyAutoFlows).toHaveBeenCalled();
1810
+ expect(model.dispatchEvent).toHaveBeenCalledWith('beforeRender', undefined, {
1811
+ useCache: false,
1812
+ });
1700
1813
  } finally {
1701
1814
  consoleSpy.mockRestore();
1702
1815
  }
@@ -1713,12 +1826,14 @@ describe('FlowModel', () => {
1713
1826
 
1714
1827
  const serialized = model.serialize();
1715
1828
 
1716
- expect(serialized).toEqual({
1717
- uid: model.uid,
1718
- stepParams: expect.objectContaining({ flow1: { step1: { param1: 'value1' } } }),
1719
- sortIndex: 5,
1720
- subModels: expect.any(Object),
1721
- });
1829
+ expect(serialized).toEqual(
1830
+ expect.objectContaining({
1831
+ uid: model.uid,
1832
+ stepParams: expect.objectContaining({ flow1: { step1: { param1: 'value1' } } }),
1833
+ sortIndex: 5,
1834
+ subModels: expect.any(Object),
1835
+ }),
1836
+ );
1722
1837
  // props should be excluded from serialization
1723
1838
  expect(serialized.props).toBeUndefined();
1724
1839
  expect(serialized.flowEngine).toBeUndefined();
@@ -1736,12 +1851,14 @@ describe('FlowModel', () => {
1736
1851
 
1737
1852
  const serialized = emptyModel.serialize();
1738
1853
 
1739
- expect(serialized).toEqual({
1740
- uid: 'empty-model',
1741
- stepParams: expect.any(Object),
1742
- sortIndex: expect.any(Number),
1743
- subModels: expect.any(Object),
1744
- });
1854
+ expect(serialized).toEqual(
1855
+ expect.objectContaining({
1856
+ uid: 'empty-model',
1857
+ stepParams: expect.any(Object),
1858
+ sortIndex: expect.any(Number),
1859
+ subModels: expect.any(Object),
1860
+ }),
1861
+ );
1745
1862
  expect(serialized.flowEngine).toBeUndefined();
1746
1863
  });
1747
1864
  });
@@ -2039,16 +2156,16 @@ describe('FlowModel', () => {
2039
2156
  vi.restoreAllMocks();
2040
2157
  });
2041
2158
 
2042
- describe('invalidateAutoFlowCache', () => {
2159
+ describe('invalidateFlowCache', () => {
2043
2160
  test('should delete auto flow cache for current model', () => {
2044
- const expectedCacheKey = 'autoFlow-all-test-model-uid';
2161
+ const expectedCacheKey = 'event:beforeRender-beforeRender-test-model-uid';
2045
2162
  realFlowEngine.applyFlowCache.set(expectedCacheKey, {
2046
2163
  status: 'resolved',
2047
2164
  data: [],
2048
2165
  promise: Promise.resolve([]),
2049
2166
  });
2050
2167
 
2051
- model.invalidateAutoFlowCache();
2168
+ model.invalidateFlowCache('beforeRender');
2052
2169
 
2053
2170
  expect(deleteSpy).toHaveBeenCalledWith(expectedCacheKey);
2054
2171
  });
@@ -2057,8 +2174,8 @@ describe('FlowModel', () => {
2057
2174
  const fork1 = model.createFork();
2058
2175
  const fork2 = model.createFork();
2059
2176
 
2060
- const fork1CacheKey = `${fork1.forkId}-all-test-model-uid`;
2061
- const fork2CacheKey = `${fork2.forkId}-all-test-model-uid`;
2177
+ const fork1CacheKey = `event:beforeRender:${fork1.forkId}-beforeRender-test-model-uid`;
2178
+ const fork2CacheKey = `event:beforeRender:${fork2.forkId}-beforeRender-test-model-uid`;
2062
2179
 
2063
2180
  realFlowEngine.applyFlowCache.set(fork1CacheKey, {
2064
2181
  status: 'resolved',
@@ -2071,7 +2188,7 @@ describe('FlowModel', () => {
2071
2188
  promise: Promise.resolve([]),
2072
2189
  });
2073
2190
 
2074
- model.invalidateAutoFlowCache();
2191
+ model.invalidateFlowCache('beforeRender');
2075
2192
 
2076
2193
  expect(deleteSpy).toHaveBeenCalledWith(fork1CacheKey);
2077
2194
  expect(deleteSpy).toHaveBeenCalledWith(fork2CacheKey);
@@ -2081,27 +2198,27 @@ describe('FlowModel', () => {
2081
2198
  const childModel1 = new FlowModel({ uid: 'child1', flowEngine: realFlowEngine });
2082
2199
  const childModel2 = new FlowModel({ uid: 'child2', flowEngine: realFlowEngine });
2083
2200
 
2084
- const child1Spy = vi.spyOn(childModel1, 'invalidateAutoFlowCache');
2085
- const child2Spy = vi.spyOn(childModel2, 'invalidateAutoFlowCache');
2201
+ const child1Spy = vi.spyOn(childModel1, 'invalidateFlowCache');
2202
+ const child2Spy = vi.spyOn(childModel2, 'invalidateFlowCache');
2086
2203
 
2087
2204
  model.addSubModel('children', childModel1);
2088
2205
  model.addSubModel('children', childModel2);
2089
2206
 
2090
- model.invalidateAutoFlowCache(true);
2207
+ model.invalidateFlowCache('beforeRender', true);
2091
2208
 
2092
- expect(child1Spy).toHaveBeenCalledWith(true);
2093
- expect(child2Spy).toHaveBeenCalledWith(true);
2209
+ expect(child1Spy).toHaveBeenCalledWith('beforeRender', true);
2210
+ expect(child2Spy).toHaveBeenCalledWith('beforeRender', true);
2094
2211
  });
2095
2212
 
2096
2213
  test('should recursively invalidate cache for object subModels', () => {
2097
2214
  const childModel = new FlowModel({ uid: 'child', flowEngine: realFlowEngine });
2098
- const childSpy = vi.spyOn(childModel, 'invalidateAutoFlowCache');
2215
+ const childSpy = vi.spyOn(childModel, 'invalidateFlowCache');
2099
2216
 
2100
2217
  model.setSubModel('child', childModel);
2101
2218
 
2102
- model.invalidateAutoFlowCache(true);
2219
+ model.invalidateFlowCache('beforeRender', true);
2103
2220
 
2104
- expect(childSpy).toHaveBeenCalledWith(true);
2221
+ expect(childSpy).toHaveBeenCalledWith('beforeRender', true);
2105
2222
  });
2106
2223
 
2107
2224
  test('should handle mixed array and object subModels', () => {
@@ -2109,25 +2226,31 @@ describe('FlowModel', () => {
2109
2226
  const arrayChild2 = new FlowModel({ uid: 'arrayChild2', flowEngine: realFlowEngine });
2110
2227
  const objectChild = new FlowModel({ uid: 'objectChild', flowEngine: realFlowEngine });
2111
2228
 
2112
- const array1Spy = vi.spyOn(arrayChild1, 'invalidateAutoFlowCache');
2113
- const array2Spy = vi.spyOn(arrayChild2, 'invalidateAutoFlowCache');
2114
- const objectSpy = vi.spyOn(objectChild, 'invalidateAutoFlowCache');
2229
+ const array1Spy = vi.spyOn(arrayChild1, 'invalidateFlowCache');
2230
+ const array2Spy = vi.spyOn(arrayChild2, 'invalidateFlowCache');
2231
+ const objectSpy = vi.spyOn(objectChild, 'invalidateFlowCache');
2115
2232
 
2116
2233
  model.addSubModel('arrayChildren', arrayChild1);
2117
2234
  model.addSubModel('arrayChildren', arrayChild2);
2118
2235
  model.setSubModel('objectChild', objectChild);
2119
2236
 
2120
- model.invalidateAutoFlowCache(true);
2237
+ model.invalidateFlowCache('beforeRender', true);
2121
2238
 
2122
- expect(array1Spy).toHaveBeenCalledWith(true);
2123
- expect(array2Spy).toHaveBeenCalledWith(true);
2124
- expect(objectSpy).toHaveBeenCalledWith(true);
2239
+ expect(array1Spy).toHaveBeenCalledWith('beforeRender', true);
2240
+ expect(array2Spy).toHaveBeenCalledWith('beforeRender', true);
2241
+ expect(objectSpy).toHaveBeenCalledWith('beforeRender', true);
2125
2242
  });
2126
2243
 
2127
2244
  test('should handle empty subModels without error', () => {
2128
- model.invalidateAutoFlowCache();
2245
+ realFlowEngine.applyFlowCache.set('event:beforeRender-beforeRender-test-model-uid', {
2246
+ status: 'resolved',
2247
+ data: [],
2248
+ promise: Promise.resolve([]),
2249
+ });
2250
+
2251
+ model.invalidateFlowCache('beforeRender');
2129
2252
 
2130
- expect(deleteSpy).toHaveBeenCalledWith('autoFlow-all-test-model-uid');
2253
+ expect(deleteSpy).toHaveBeenCalledWith('event:beforeRender-beforeRender-test-model-uid');
2131
2254
  });
2132
2255
 
2133
2256
  test('should handle null flowEngine gracefully', () => {
@@ -2135,19 +2258,19 @@ describe('FlowModel', () => {
2135
2258
  modelWithValidEngine.flowEngine = null;
2136
2259
 
2137
2260
  expect(() => {
2138
- modelWithValidEngine.invalidateAutoFlowCache();
2261
+ modelWithValidEngine.invalidateFlowCache('beforeRender');
2139
2262
  }).not.toThrow();
2140
2263
  });
2141
2264
 
2142
2265
  test('should pass deep parameter to recursive calls', () => {
2143
2266
  const childModel = new FlowModel({ uid: 'child', flowEngine: realFlowEngine });
2144
- const childSpy = vi.spyOn(childModel, 'invalidateAutoFlowCache');
2267
+ const childSpy = vi.spyOn(childModel, 'invalidateFlowCache');
2145
2268
 
2146
2269
  model.setSubModel('child', childModel);
2147
2270
 
2148
- model.invalidateAutoFlowCache(true);
2271
+ model.invalidateFlowCache('beforeRender', true);
2149
2272
 
2150
- expect(childSpy).toHaveBeenCalledWith(true);
2273
+ expect(childSpy).toHaveBeenCalledWith('beforeRender', true);
2151
2274
  });
2152
2275
  });
2153
2276
  });
@@ -2198,7 +2321,7 @@ describe('FlowModel', () => {
2198
2321
  });
2199
2322
 
2200
2323
  const handlerSpy = flow.steps.testStep.handler as any;
2201
- await model.applyAutoFlows();
2324
+ await model.dispatchEvent('beforeRender');
2202
2325
  expect(handlerSpy).toHaveBeenCalled();
2203
2326
  });
2204
2327
 
@@ -2245,7 +2368,7 @@ describe('FlowModel', () => {
2245
2368
  });
2246
2369
 
2247
2370
  const handlerSpy = flow.steps.nestedStep.handler as any;
2248
- await model.applyAutoFlows();
2371
+ await model.dispatchEvent('beforeRender');
2249
2372
  expect(handlerSpy).toHaveBeenCalled();
2250
2373
  });
2251
2374
  });