@nocobase/flow-engine 2.0.0-alpha.7 → 2.0.0-alpha.71

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 (589) hide show
  1. package/lib/BlockScopedFlowEngine.d.ts +23 -0
  2. package/lib/BlockScopedFlowEngine.js +91 -0
  3. package/lib/FlowContextProvider.d.ts +2 -2
  4. package/lib/FlowContextProvider.js +3 -3
  5. package/lib/FlowDefinition.d.ts +6 -4
  6. package/lib/JSRunner.d.ts +6 -0
  7. package/lib/JSRunner.js +27 -1
  8. package/lib/ViewScopedFlowEngine.d.ts +1 -1
  9. package/lib/ViewScopedFlowEngine.js +18 -1
  10. package/lib/acl/Acl.d.ts +12 -12
  11. package/lib/acl/Acl.js +88 -30
  12. package/lib/components/DynamicFlowsEditor.js +2 -4
  13. package/lib/components/FieldModelRenderer.js +17 -9
  14. package/lib/components/FieldSkeleton.d.ts +10 -0
  15. package/lib/components/FieldSkeleton.js +64 -0
  16. package/lib/components/FlowContextSelector.js +19 -3
  17. package/lib/components/FlowModelRenderer.d.ts +4 -6
  18. package/lib/components/FlowModelRenderer.js +35 -53
  19. package/lib/components/FormItem.js +5 -1
  20. package/lib/components/MobilePopup.d.ts +20 -0
  21. package/lib/components/MobilePopup.js +102 -0
  22. package/lib/components/MobilePopup.style.d.ts +17 -0
  23. package/lib/components/MobilePopup.style.js +186 -0
  24. package/lib/components/common/withFlowDesignMode.d.ts +1 -1
  25. package/lib/components/common/withFlowDesignMode.js +5 -5
  26. package/lib/components/dnd/gridDragPlanner.d.ts +1 -0
  27. package/lib/components/dnd/gridDragPlanner.js +53 -1
  28. package/lib/components/index.d.ts +1 -0
  29. package/lib/components/index.js +3 -1
  30. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +71 -53
  31. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +19 -0
  32. package/lib/components/settings/wrappers/component/SelectWithTitle.js +136 -0
  33. package/lib/components/settings/wrappers/component/SwitchWithTitle.d.ts +10 -0
  34. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +111 -0
  35. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +233 -97
  36. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +71 -54
  37. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
  38. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +63 -23
  39. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +13 -2
  40. package/lib/components/settings/wrappers/embedded/FlowSettings.js +42 -28
  41. package/lib/components/settings/wrappers/embedded/FlowsSettings.js +3 -3
  42. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +52 -32
  43. package/lib/components/subModel/AddSubModelButton.d.ts +7 -0
  44. package/lib/components/subModel/AddSubModelButton.js +78 -8
  45. package/lib/components/subModel/LazyDropdown.js +14 -15
  46. package/lib/components/subModel/utils.d.ts +1 -1
  47. package/lib/components/subModel/utils.js +21 -11
  48. package/lib/components/variables/VariableInput.js +26 -6
  49. package/lib/components/variables/VariableTag.js +43 -2
  50. package/lib/components/variables/types.d.ts +2 -0
  51. package/lib/components/variables/utils.js +4 -2
  52. package/lib/data-source/index.d.ts +23 -4
  53. package/lib/data-source/index.js +135 -14
  54. package/lib/data-source/jioToJoiSchema.js +1 -0
  55. package/lib/emitter.d.ts +6 -0
  56. package/lib/emitter.js +12 -0
  57. package/lib/executor/FlowExecutor.d.ts +6 -6
  58. package/lib/executor/FlowExecutor.js +302 -99
  59. package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
  60. package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
  61. package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
  62. package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
  63. package/lib/flowContext.d.ts +105 -6
  64. package/lib/flowContext.js +447 -139
  65. package/lib/flowEngine.d.ts +71 -1
  66. package/lib/flowEngine.js +319 -16
  67. package/lib/flowSettings.d.ts +4 -3
  68. package/lib/flowSettings.js +45 -21
  69. package/lib/hooks/useApplyAutoFlows.d.ts +1 -0
  70. package/lib/hooks/useApplyAutoFlows.js +3 -2
  71. package/lib/index.d.ts +14 -3
  72. package/lib/index.js +54 -7
  73. package/lib/locale/de-DE.json +62 -0
  74. package/lib/locale/en-US.json +57 -45
  75. package/lib/locale/es-ES.json +62 -0
  76. package/lib/locale/fr-FR.json +62 -0
  77. package/lib/locale/hu-HU.json +62 -0
  78. package/lib/locale/id-ID.json +62 -0
  79. package/lib/locale/index.d.ts +114 -90
  80. package/lib/locale/it-IT.json +62 -0
  81. package/lib/locale/ja-JP.json +62 -0
  82. package/lib/locale/ko-KR.json +62 -0
  83. package/lib/locale/nl-NL.json +62 -0
  84. package/lib/locale/pt-BR.json +62 -0
  85. package/lib/locale/ru-RU.json +62 -0
  86. package/lib/locale/tr-TR.json +62 -0
  87. package/lib/locale/uk-UA.json +62 -0
  88. package/lib/locale/vi-VN.json +62 -0
  89. package/lib/locale/zh-CN.json +58 -46
  90. package/lib/locale/zh-TW.json +62 -0
  91. package/lib/models/CollectionFieldModel.d.ts +7 -2
  92. package/lib/models/CollectionFieldModel.js +63 -16
  93. package/lib/models/flowModel.d.ts +76 -32
  94. package/lib/models/flowModel.js +300 -112
  95. package/lib/models/forkFlowModel.d.ts +8 -4
  96. package/lib/models/forkFlowModel.js +38 -8
  97. package/lib/provider.d.ts +3 -1
  98. package/lib/provider.js +14 -11
  99. package/lib/reactive/index.d.ts +10 -0
  100. package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → reactive/index.js} +14 -15
  101. package/lib/reactive/observer.d.ts +19 -0
  102. package/lib/reactive/observer.js +109 -0
  103. package/lib/resources/baseRecordResource.d.ts +6 -0
  104. package/lib/resources/baseRecordResource.js +38 -3
  105. package/lib/resources/multiRecordResource.d.ts +5 -2
  106. package/lib/resources/multiRecordResource.js +26 -10
  107. package/lib/resources/singleRecordResource.js +8 -3
  108. package/lib/resources/sqlResource.d.ts +5 -3
  109. package/lib/resources/sqlResource.js +30 -28
  110. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  111. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +37 -20
  112. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  113. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  114. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  115. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  116. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  117. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  118. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
  119. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
  120. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  121. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  122. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  123. package/lib/runjs-context/contexts/JSItemRunJSContext.js +34 -20
  124. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  125. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  126. package/lib/runjs-context/contexts/base.d.ts +9 -0
  127. package/lib/runjs-context/contexts/base.js +879 -0
  128. package/lib/runjs-context/contributions.d.ts +33 -0
  129. package/lib/runjs-context/contributions.js +88 -0
  130. package/lib/runjs-context/helpers.d.ts +5 -2
  131. package/lib/runjs-context/helpers.js +36 -27
  132. package/lib/runjs-context/registry.d.ts +7 -4
  133. package/lib/runjs-context/registry.js +10 -42
  134. package/lib/runjs-context/setup.d.ts +9 -0
  135. package/lib/runjs-context/setup.js +88 -0
  136. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  137. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  138. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  139. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  140. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  141. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  142. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  143. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  144. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  145. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  146. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  147. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  148. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  149. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  150. package/lib/runjs-context/snippets/index.d.ts +24 -3
  151. package/lib/runjs-context/snippets/index.js +183 -40
  152. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  153. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  154. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  155. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  156. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  157. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  158. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  159. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  160. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  161. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  162. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  163. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  164. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  165. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  166. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  167. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  168. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  169. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  170. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  171. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  172. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  173. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  174. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  175. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  176. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  177. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  178. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  179. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  180. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  181. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  182. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  183. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  184. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  185. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  186. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  187. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  188. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  189. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  190. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  191. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  192. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  193. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  194. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  195. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  196. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  197. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  198. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  199. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  200. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  201. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  202. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  203. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  204. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  205. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  206. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  207. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  208. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  209. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  210. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  211. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  212. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  213. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  214. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  215. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  216. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  217. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  218. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  219. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  220. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  221. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  222. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  223. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  224. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  225. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  226. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  227. package/lib/runjs-context/snippets/types.d.ts +9 -1
  228. package/lib/runjsLibs.d.ts +28 -0
  229. package/lib/runjsLibs.js +532 -0
  230. package/lib/scheduler/ModelOperationScheduler.d.ts +53 -0
  231. package/lib/scheduler/ModelOperationScheduler.js +262 -0
  232. package/lib/types.d.ts +66 -7
  233. package/lib/types.js +4 -3
  234. package/lib/utils/associationObjectVariable.d.ts +32 -0
  235. package/lib/utils/associationObjectVariable.js +157 -0
  236. package/lib/utils/createCollectionContextMeta.d.ts +1 -1
  237. package/lib/utils/createCollectionContextMeta.js +9 -4
  238. package/lib/utils/createEphemeralContext.d.ts +13 -0
  239. package/lib/utils/createEphemeralContext.js +140 -0
  240. package/lib/utils/flows.d.ts +10 -0
  241. package/lib/{runjs-context/snippets/global/console-log-ctx.snippet.js → utils/flows.js} +21 -14
  242. package/lib/utils/index.d.ts +9 -3
  243. package/lib/utils/index.js +30 -2
  244. package/lib/utils/jsxTransform.d.ts +15 -0
  245. package/lib/utils/jsxTransform.js +68 -0
  246. package/lib/utils/params-resolvers.js +19 -12
  247. package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
  248. package/lib/utils/parsePathnameToViewParams.js +41 -5
  249. package/lib/utils/pruneFilter.d.ts +21 -0
  250. package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
  251. package/lib/utils/resolveModuleUrl.d.ts +58 -0
  252. package/lib/utils/resolveModuleUrl.js +65 -0
  253. package/lib/utils/runjsModuleLoader.d.ts +58 -0
  254. package/lib/utils/runjsModuleLoader.js +422 -0
  255. package/lib/utils/runjsTemplateCompat.d.ts +35 -0
  256. package/lib/utils/runjsTemplateCompat.js +743 -0
  257. package/lib/utils/safeGlobals.d.ts +6 -8
  258. package/lib/utils/safeGlobals.js +169 -14
  259. package/lib/utils/schema-utils.d.ts +6 -0
  260. package/lib/utils/schema-utils.js +71 -6
  261. package/lib/utils/serverContextParams.d.ts +4 -0
  262. package/lib/utils/serverContextParams.js +2 -0
  263. package/lib/utils/translation.d.ts +4 -1
  264. package/lib/utils/translation.js +6 -2
  265. package/lib/utils/variablesParams.d.ts +22 -5
  266. package/lib/utils/variablesParams.js +141 -61
  267. package/lib/views/DialogComponent.js +1 -5
  268. package/lib/views/DrawerComponent.js +18 -9
  269. package/lib/views/PageComponent.js +5 -5
  270. package/lib/views/ViewNavigation.d.ts +11 -15
  271. package/lib/views/ViewNavigation.js +37 -19
  272. package/lib/views/createViewMeta.d.ts +27 -5
  273. package/lib/views/createViewMeta.js +338 -72
  274. package/lib/views/index.d.ts +1 -1
  275. package/lib/views/index.js +4 -0
  276. package/lib/views/useDialog.d.ts +10 -9
  277. package/lib/views/useDialog.js +46 -34
  278. package/lib/views/useDrawer.d.ts +10 -9
  279. package/lib/views/useDrawer.js +74 -48
  280. package/lib/views/usePage.d.ts +14 -9
  281. package/lib/views/usePage.js +82 -33
  282. package/lib/views/usePopover.js +4 -1
  283. package/lib/views/viewEvents.d.ts +17 -0
  284. package/lib/views/viewEvents.js +90 -0
  285. package/package.json +6 -3
  286. package/src/BlockScopedFlowEngine.ts +85 -0
  287. package/src/FlowContextProvider.tsx +4 -2
  288. package/src/JSRunner.ts +39 -1
  289. package/src/ViewScopedFlowEngine.ts +21 -1
  290. package/src/__tests__/JSRunner.test.ts +125 -52
  291. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  292. package/src/__tests__/createViewMeta.popup.test.ts +203 -0
  293. package/src/__tests__/flow-engine.test.ts +3 -0
  294. package/src/__tests__/flowContext.test.ts +160 -0
  295. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  296. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
  297. package/src/__tests__/flowEngine.destroyModel.test.ts +74 -0
  298. package/src/__tests__/flowEngine.moveModel.test.ts +43 -0
  299. package/src/__tests__/flowEngine.removeModel.test.ts +72 -0
  300. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  301. package/src/__tests__/flowModel.openView.navigation.test.ts +31 -2
  302. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  303. package/src/__tests__/flowSettings.open.test.tsx +71 -15
  304. package/src/__tests__/flowSettings.test.ts +2 -0
  305. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  306. package/src/__tests__/modelOperationScheduler.test.ts +346 -0
  307. package/src/__tests__/objectVariable.test.ts +464 -0
  308. package/src/__tests__/provider.test.tsx +0 -5
  309. package/src/__tests__/runjsContext.test.ts +219 -35
  310. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  311. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  312. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  313. package/src/__tests__/runjsExternalLibs.test.ts +242 -0
  314. package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
  315. package/src/__tests__/runjsLocales.test.ts +39 -0
  316. package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
  317. package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
  318. package/src/__tests__/runjsSnippets.test.ts +140 -0
  319. package/src/__tests__/viewScopedFlowEngine.test.ts +101 -3
  320. package/src/acl/Acl.tsx +85 -31
  321. package/src/acl/__tests__/Acl.test.tsx +43 -1
  322. package/src/components/DynamicFlowsEditor.tsx +0 -10
  323. package/src/components/FieldModelRenderer.tsx +22 -9
  324. package/src/components/FieldSkeleton.tsx +27 -0
  325. package/src/components/FlowContextSelector.tsx +20 -2
  326. package/src/components/FlowModelRenderer.tsx +52 -84
  327. package/src/components/FormItem.tsx +8 -1
  328. package/src/components/MobilePopup.style.ts +220 -0
  329. package/src/components/MobilePopup.tsx +86 -0
  330. package/src/components/__tests__/FlowModelRenderer.test.tsx +89 -0
  331. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
  332. package/src/components/__tests__/gridDragPlanner.test.ts +141 -1
  333. package/src/components/common/withFlowDesignMode.tsx +5 -5
  334. package/src/components/dnd/gridDragPlanner.ts +60 -0
  335. package/src/components/index.ts +1 -0
  336. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +34 -17
  337. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +110 -0
  338. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +83 -0
  339. package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
  340. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +272 -125
  341. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +34 -18
  342. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +56 -18
  343. package/src/components/settings/wrappers/contextual/StepSettings.tsx +1 -2
  344. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -1
  345. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +624 -0
  346. package/src/components/settings/wrappers/embedded/FlowSettings.tsx +47 -35
  347. package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +1 -1
  348. package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +64 -42
  349. package/src/components/subModel/AddSubModelButton.tsx +104 -9
  350. package/src/components/subModel/LazyDropdown.tsx +14 -14
  351. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +168 -7
  352. package/src/components/subModel/__tests__/utils.test.ts +12 -12
  353. package/src/components/subModel/utils.ts +25 -6
  354. package/src/components/variables/VariableInput.tsx +32 -6
  355. package/src/components/variables/VariableTag.tsx +54 -2
  356. package/src/components/variables/types.ts +2 -0
  357. package/src/components/variables/utils.ts +7 -3
  358. package/src/data-source/index.ts +143 -12
  359. package/src/data-source/jioToJoiSchema.ts +1 -0
  360. package/src/emitter.ts +14 -0
  361. package/src/executor/FlowExecutor.ts +383 -119
  362. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  363. package/src/executor/__tests__/flowExecutor.test.ts +217 -5
  364. package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
  365. package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
  366. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
  367. package/src/flowContext.ts +646 -158
  368. package/src/flowEngine.ts +385 -14
  369. package/src/flowSettings.ts +59 -30
  370. package/src/hooks/useApplyAutoFlows.ts +5 -3
  371. package/src/index.ts +26 -3
  372. package/src/locale/de-DE.json +62 -0
  373. package/src/locale/en-US.json +57 -45
  374. package/src/locale/es-ES.json +62 -0
  375. package/src/locale/fr-FR.json +62 -0
  376. package/src/locale/hu-HU.json +62 -0
  377. package/src/locale/id-ID.json +62 -0
  378. package/src/locale/it-IT.json +62 -0
  379. package/src/locale/ja-JP.json +62 -0
  380. package/src/locale/ko-KR.json +62 -0
  381. package/src/locale/nl-NL.json +62 -0
  382. package/src/locale/pt-BR.json +62 -0
  383. package/src/locale/ru-RU.json +62 -0
  384. package/src/locale/tr-TR.json +62 -0
  385. package/src/locale/uk-UA.json +62 -0
  386. package/src/locale/vi-VN.json +62 -0
  387. package/src/locale/zh-CN.json +58 -46
  388. package/src/locale/zh-TW.json +62 -0
  389. package/src/models/CollectionFieldModel.tsx +82 -18
  390. package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
  391. package/src/models/__tests__/dispatchEvent.when.test.ts +356 -0
  392. package/src/models/__tests__/flowEngine.resolveUse.test.ts +170 -0
  393. package/src/models/__tests__/flowModel.clone.test.ts +416 -0
  394. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
  395. package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
  396. package/src/models/__tests__/flowModel.test.ts +296 -119
  397. package/src/models/__tests__/forkFlowModel.test.ts +40 -7
  398. package/src/models/flowModel.tsx +426 -148
  399. package/src/models/forkFlowModel.ts +48 -8
  400. package/src/provider.tsx +18 -14
  401. package/src/reactive/__tests__/observer.test.tsx +211 -0
  402. package/src/reactive/index.ts +11 -0
  403. package/src/reactive/observer.tsx +101 -0
  404. package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
  405. package/src/resources/__tests__/sqlResource.test.ts +60 -0
  406. package/src/resources/baseRecordResource.ts +46 -3
  407. package/src/resources/multiRecordResource.ts +28 -12
  408. package/src/resources/singleRecordResource.ts +9 -3
  409. package/src/resources/sqlResource.ts +33 -32
  410. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +38 -21
  411. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +50 -34
  412. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  413. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  414. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
  415. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  416. package/src/runjs-context/contexts/JSItemRunJSContext.ts +35 -21
  417. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  418. package/src/runjs-context/contexts/base.ts +871 -0
  419. package/src/runjs-context/contributions.ts +88 -0
  420. package/src/runjs-context/helpers.ts +32 -30
  421. package/src/runjs-context/registry.ts +16 -47
  422. package/src/runjs-context/setup.ts +57 -0
  423. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  424. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  425. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  426. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  427. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  428. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  429. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  430. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  431. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  432. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  433. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  434. package/src/runjs-context/snippets/index.ts +212 -39
  435. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  436. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  437. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  438. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  439. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  440. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  441. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  442. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  443. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  444. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  445. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  446. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  447. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  448. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  449. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  450. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  451. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  452. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  453. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  454. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  455. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  456. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  457. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  458. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  459. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  460. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  461. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  462. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  463. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  464. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  465. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  466. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  467. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  468. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  469. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  470. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  471. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  472. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  473. package/src/runjs-context/snippets/types.ts +5 -1
  474. package/src/runjsLibs.ts +622 -0
  475. package/src/scheduler/ModelOperationScheduler.ts +306 -0
  476. package/src/types.ts +86 -5
  477. package/src/utils/__tests__/createCollectionContextMeta.test.ts +51 -0
  478. package/src/utils/__tests__/flows.test.ts +65 -0
  479. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  480. package/src/utils/__tests__/params-resolvers.test.ts +40 -0
  481. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
  482. package/src/utils/__tests__/pruneFilter.test.ts +38 -0
  483. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
  484. package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
  485. package/src/utils/__tests__/safeGlobals.test.ts +79 -2
  486. package/src/utils/__tests__/utils.test.ts +114 -15
  487. package/src/utils/__tests__/variablesParams.test.ts +120 -0
  488. package/src/utils/associationObjectVariable.ts +180 -0
  489. package/src/utils/createCollectionContextMeta.ts +9 -3
  490. package/src/utils/createEphemeralContext.ts +142 -0
  491. package/src/utils/flows.ts +23 -0
  492. package/src/utils/index.ts +17 -3
  493. package/src/utils/jsxTransform.ts +39 -0
  494. package/src/utils/params-resolvers.ts +25 -11
  495. package/src/utils/parsePathnameToViewParams.ts +50 -6
  496. package/src/utils/pruneFilter.ts +41 -0
  497. package/src/utils/resolveModuleUrl.ts +91 -0
  498. package/src/utils/runjsModuleLoader.ts +553 -0
  499. package/src/utils/runjsTemplateCompat.ts +828 -0
  500. package/src/utils/safeGlobals.ts +181 -15
  501. package/src/utils/schema-utils.ts +81 -3
  502. package/src/utils/serverContextParams.ts +6 -0
  503. package/src/utils/translation.ts +7 -2
  504. package/src/utils/variablesParams.ts +164 -72
  505. package/src/views/DialogComponent.tsx +1 -4
  506. package/src/views/DrawerComponent.tsx +19 -7
  507. package/src/views/PageComponent.tsx +3 -5
  508. package/src/views/ViewNavigation.ts +49 -43
  509. package/src/views/__tests__/FlowView.usePage.test.tsx +186 -0
  510. package/src/views/__tests__/ViewNavigation.test.ts +54 -34
  511. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +159 -0
  512. package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
  513. package/src/views/createViewMeta.ts +402 -73
  514. package/src/views/index.tsx +1 -1
  515. package/src/views/useDialog.tsx +52 -31
  516. package/src/views/useDrawer.tsx +99 -55
  517. package/src/views/usePage.tsx +101 -33
  518. package/src/views/usePopover.tsx +4 -1
  519. package/src/views/viewEvents.ts +55 -0
  520. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  521. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  522. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  523. package/lib/runjs-context/index.d.ts +0 -19
  524. package/lib/runjs-context/index.js +0 -57
  525. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  526. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  527. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  528. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  529. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
  530. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  531. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  532. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  533. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  534. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  535. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  536. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  537. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  538. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  539. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  540. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  541. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  542. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  543. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  544. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +0 -46
  545. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  546. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  547. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  548. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  549. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  550. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  551. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  552. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  553. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  554. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  555. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  556. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  557. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  558. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  559. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  560. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  561. package/src/runjs-context/index.ts +0 -20
  562. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  563. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  564. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  565. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  566. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  567. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  568. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  569. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  570. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  571. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  572. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  573. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  574. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  575. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  576. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  577. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  578. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  579. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  580. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  581. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  582. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  583. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  584. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  585. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  586. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  587. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  588. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  589. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -0,0 +1,306 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { uid as genUid } from 'uid/secure';
11
+ import type { FlowEngine } from '../flowEngine';
12
+ import type { FlowModel } from '../models/flowModel';
13
+
14
+ type LifecycleType =
15
+ | 'created'
16
+ | 'mounted'
17
+ | 'unmounted'
18
+ | 'destroyed'
19
+ | `event:${string}:start`
20
+ | `event:${string}:end`
21
+ | `event:${string}:error`;
22
+
23
+ export type ScheduleWhen = LifecycleType | ((e: LifecycleEvent) => boolean);
24
+
25
+ export interface ScheduleOptions {
26
+ when?: ScheduleWhen;
27
+ }
28
+
29
+ export type ScheduledCancel = () => boolean;
30
+
31
+ export interface LifecycleEvent {
32
+ type: LifecycleType;
33
+ uid: string;
34
+ model?: FlowModel;
35
+ runId?: string;
36
+ error?: any;
37
+ inputArgs?: Record<string, any>;
38
+ result?: any;
39
+ flowKey?: string;
40
+ stepKey?: string;
41
+ }
42
+
43
+ type ScheduledItem = {
44
+ id: string;
45
+ fromUid: string;
46
+ toUid: string;
47
+ fn: (model: FlowModel) => Promise<void> | void;
48
+ options: ScheduleOptions;
49
+ };
50
+
51
+ export class ModelOperationScheduler {
52
+ private itemsByTargetUid = new Map<string, Map<string, ScheduledItem>>();
53
+ private itemIdsByFromUid = new Map<string, Set<string>>();
54
+ private itemsById = new Map<string, ScheduledItem>();
55
+
56
+ private unbindHandlers: Array<() => void> = [];
57
+ private subscribedEventNames = new Set<string>();
58
+
59
+ constructor(private engine: FlowEngine) {
60
+ this.bindEngineLifecycle();
61
+ }
62
+
63
+ /** 外部调用入口 */
64
+ schedule(
65
+ fromModelOrUid: FlowModel | string,
66
+ toUid: string,
67
+ fn: (model: FlowModel) => Promise<void> | void,
68
+ options?: ScheduleOptions,
69
+ ): ScheduledCancel {
70
+ const fromUid = typeof fromModelOrUid === 'string' ? fromModelOrUid : fromModelOrUid?.uid;
71
+ if (!fromUid) {
72
+ throw new Error('scheduleModelOperation: invalid from model or uid');
73
+ }
74
+ if (!toUid || typeof toUid !== 'string') {
75
+ throw new Error('scheduleModelOperation: invalid target uid');
76
+ }
77
+
78
+ const item: ScheduledItem = {
79
+ id: genUid(),
80
+ fromUid,
81
+ toUid,
82
+ fn,
83
+ options: {
84
+ // 默认语义:仅当 when === 'created' 时,对“已存在的目标”进行一次立即执行;
85
+ // 其它 when 不做立即执行,需等待后续真实生命周期事件。
86
+ when: options?.when ?? 'created',
87
+ },
88
+ };
89
+
90
+ // 注册结构
91
+ let targetMap = this.itemsByTargetUid.get(toUid);
92
+ if (!targetMap) {
93
+ targetMap = new Map();
94
+ this.itemsByTargetUid.set(toUid, targetMap);
95
+ }
96
+ targetMap.set(item.id, item);
97
+ let fromSet = this.itemIdsByFromUid.get(fromUid);
98
+ if (!fromSet) {
99
+ fromSet = new Set();
100
+ this.itemIdsByFromUid.set(fromUid, fromSet);
101
+ }
102
+ fromSet.add(item.id);
103
+ this.itemsById.set(item.id, item);
104
+
105
+ // 若是 event:xxx:start/end 语义,确保已订阅对应的 model:event 通道
106
+ this.ensureEventSubscriptionIfNeeded(item.options.when);
107
+
108
+ const modelNow = this.engine.getModel<FlowModel>(toUid);
109
+ if (modelNow && item.options.when === 'created') {
110
+ // 仅 when === 'created' 时,对“已存在的目标”立即执行一次
111
+ void this.tryExecuteOnce(item.id, { type: 'created', uid: toUid, model: modelNow });
112
+ }
113
+
114
+ return () => this.internalCancel(item.id);
115
+ }
116
+
117
+ cancel(filter: { fromUid?: string; toUid?: string }) {
118
+ const { fromUid, toUid } = filter || {};
119
+ if (toUid && this.itemsByTargetUid.has(toUid)) {
120
+ const map = this.itemsByTargetUid.get(toUid);
121
+ if (map)
122
+ for (const item of map.values()) {
123
+ if (fromUid && item.fromUid !== fromUid) continue;
124
+ this.internalCancel(item.id);
125
+ }
126
+ return;
127
+ }
128
+ if (fromUid && this.itemIdsByFromUid.has(fromUid)) {
129
+ const set = this.itemIdsByFromUid.get(fromUid);
130
+ if (set)
131
+ for (const id of Array.from(set)) {
132
+ const it = this.itemsById.get(id);
133
+ if (!it) continue;
134
+ if (toUid && it.toUid !== toUid) continue;
135
+ this.internalCancel(id);
136
+ }
137
+ }
138
+ }
139
+
140
+ /** 引擎关闭时释放 */
141
+ dispose() {
142
+ try {
143
+ for (const unbind of this.unbindHandlers) {
144
+ try {
145
+ unbind();
146
+ } catch (err) {
147
+ // 忽略解绑异常
148
+ void err;
149
+ }
150
+ }
151
+ } finally {
152
+ this.unbindHandlers = [];
153
+ }
154
+
155
+ // 统一取消剩余任务(将触发 cleanupItem,从而移除 abort 监听与计时器)
156
+ for (const map of this.itemsByTargetUid.values()) {
157
+ for (const item of map.values()) this.internalCancel(item.id);
158
+ }
159
+ this.itemsByTargetUid.clear();
160
+ this.itemIdsByFromUid.clear();
161
+ }
162
+
163
+ private bindEngineLifecycle() {
164
+ const emitter = this.engine.emitter;
165
+ if (!emitter || typeof emitter.on !== 'function') return;
166
+
167
+ const onCreated = async (e: LifecycleEvent) => {
168
+ await this.processLifecycleEvent(e.uid, { ...e, type: 'created' });
169
+ };
170
+ emitter.on('model:created', onCreated);
171
+ this.unbindHandlers.push(() => emitter.off('model:created', onCreated));
172
+
173
+ const onMounted = async (e: LifecycleEvent) => {
174
+ await this.processLifecycleEvent(e.uid, { ...e, type: 'mounted' });
175
+ };
176
+ emitter.on('model:mounted', onMounted);
177
+ this.unbindHandlers.push(() => emitter.off('model:mounted', onMounted));
178
+
179
+ const onGenericBeforeStart = async (e: LifecycleEvent) => {
180
+ await this.processLifecycleEvent(e.uid, { ...e, type: 'event:beforeRender:start' });
181
+ };
182
+ emitter.on('model:event:beforeRender:start', onGenericBeforeStart);
183
+ this.unbindHandlers.push(() => emitter.off('model:event:beforeRender:start', onGenericBeforeStart));
184
+
185
+ const onGenericBeforeEnd = async (e: LifecycleEvent) => {
186
+ await this.processLifecycleEvent(e.uid, { ...e, type: 'event:beforeRender:end' });
187
+ };
188
+ emitter.on('model:event:beforeRender:end', onGenericBeforeEnd);
189
+ this.unbindHandlers.push(() => emitter.off('model:event:beforeRender:end', onGenericBeforeEnd));
190
+
191
+ const onUnmounted = async (e: LifecycleEvent) => {
192
+ await this.processLifecycleEvent(e.uid, { ...e, type: 'unmounted' });
193
+ };
194
+ emitter.on('model:unmounted', onUnmounted);
195
+ this.unbindHandlers.push(() => emitter.off('model:unmounted', onUnmounted));
196
+
197
+ const onDestroyed = async (e: LifecycleEvent) => {
198
+ const targetBucket = this.itemsByTargetUid.get(e.uid);
199
+ const event = { ...e, type: 'destroyed' as const };
200
+ if (targetBucket && targetBucket.size) {
201
+ const ids = Array.from(targetBucket.keys());
202
+ for (const id of ids) {
203
+ const it = this.itemsById.get(id);
204
+ if (!it) continue;
205
+ if (this.shouldTrigger(it.options.when, event)) {
206
+ await this.tryExecuteOnce(id, event);
207
+ } else {
208
+ this.internalCancel(id);
209
+ }
210
+ }
211
+ }
212
+ };
213
+ emitter.on('model:destroyed', onDestroyed);
214
+ this.unbindHandlers.push(() => emitter.off('model:destroyed', onDestroyed));
215
+ }
216
+
217
+ private ensureEventSubscriptionIfNeeded(when?: ScheduleWhen) {
218
+ if (!when || typeof when !== 'string') return;
219
+ const parsed = this.parseEventWhen(when);
220
+ if (!parsed) return;
221
+ const { name } = parsed;
222
+ if (this.subscribedEventNames.has(name)) return;
223
+ this.subscribedEventNames.add(name);
224
+ const emitter = this.engine.emitter;
225
+ const onStart = async (e: LifecycleEvent) => {
226
+ await this.processLifecycleEvent(e.uid, { ...e, type: `event:${name}:start` as LifecycleType });
227
+ };
228
+ const onEnd = async (e: LifecycleEvent) => {
229
+ await this.processLifecycleEvent(e.uid, { ...e, type: `event:${name}:end` as LifecycleType });
230
+ };
231
+ const onError = async (e: LifecycleEvent) => {
232
+ await this.processLifecycleEvent(e.uid, { ...e, type: `event:${name}:error` as LifecycleType });
233
+ };
234
+ emitter.on(`model:event:${name}:start`, onStart);
235
+ emitter.on(`model:event:${name}:end`, onEnd);
236
+ emitter.on(`model:event:${name}:error`, onError);
237
+ this.unbindHandlers.push(() => emitter.off(`model:event:${name}:start`, onStart));
238
+ this.unbindHandlers.push(() => emitter.off(`model:event:${name}:end`, onEnd));
239
+ this.unbindHandlers.push(() => emitter.off(`model:event:${name}:error`, onError));
240
+ }
241
+
242
+ private parseEventWhen(when?: ScheduleWhen): { name: string; phase: 'start' | 'end' | 'error' } | null {
243
+ if (!when || typeof when !== 'string') return null;
244
+ const m = /^event:(.+):(start|end|error)$/.exec(when);
245
+ if (!m) return null;
246
+ return { name: m[1], phase: m[2] as 'start' | 'end' | 'error' };
247
+ }
248
+
249
+ private async processLifecycleEvent(targetUid: string, event: LifecycleEvent) {
250
+ const targetBucket = this.itemsByTargetUid.get(targetUid);
251
+ if (!targetBucket || targetBucket.size === 0) return;
252
+ const ids = Array.from(targetBucket.keys());
253
+ for (const id of ids) {
254
+ const item = this.itemsById.get(id);
255
+ if (!item) continue;
256
+ const should = this.shouldTrigger(item.options.when, event);
257
+ if (!should) continue;
258
+ await this.tryExecuteOnce(id, event);
259
+ }
260
+ }
261
+
262
+ private shouldTrigger(when: ScheduleWhen | undefined, event: LifecycleEvent): boolean {
263
+ if (!when) return false;
264
+ if (typeof when === 'function') return !!when(event);
265
+ return when === event.type;
266
+ }
267
+
268
+ private async tryExecuteOnce(id: string, event: LifecycleEvent) {
269
+ const item = this.takeItem(id);
270
+ if (!item) return;
271
+ try {
272
+ const model = event.model || this.engine.getModel<FlowModel>(item.toUid);
273
+ if (!model) return;
274
+ await Promise.resolve(item.fn(model));
275
+ } catch (err) {
276
+ this.engine.logger?.error?.(
277
+ { err, id, fromUid: item.fromUid, toUid: item.toUid, when: item.options.when },
278
+ 'ModelOperationScheduler: operation execution failed',
279
+ );
280
+ }
281
+ }
282
+
283
+ private internalCancel(id: string) {
284
+ return !!this.takeItem(id);
285
+ }
286
+
287
+ private takeItem(id: string): ScheduledItem | undefined {
288
+ const it = this.itemsById.get(id);
289
+ if (!it) return undefined;
290
+ const { toUid, fromUid } = it;
291
+ const map = this.itemsByTargetUid.get(toUid);
292
+ if (map) {
293
+ map.delete(id);
294
+ if (map.size === 0) this.itemsByTargetUid.delete(toUid);
295
+ }
296
+ const set = this.itemIdsByFromUid.get(fromUid);
297
+ if (set) {
298
+ set.delete(id);
299
+ if (set.size === 0) this.itemIdsByFromUid.delete(fromUid);
300
+ }
301
+ this.itemsById.delete(id);
302
+ return it;
303
+ }
304
+ }
305
+
306
+ export default ModelOperationScheduler;
package/src/types.ts CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { ISchema } from '@formily/json-schema';
11
11
  import { SubModelItem } from './components';
12
+ import type { PropertyOptions } from './flowContext';
12
13
  import { FlowContext, FlowModelContext, FlowRuntimeContext, FlowSettingsContext } from './flowContext';
13
14
  import type { FlowEngine } from './flowEngine';
14
15
  import type { FlowModel } from './models';
@@ -109,6 +110,8 @@ export interface FlowDefinitionOptions<TModel extends FlowModel = FlowModel> {
109
110
  * 仅填补缺失,不覆盖已有。固定返回形状:{ [stepKey]: params }
110
111
  */
111
112
  defaultParams?: Record<string, any> | ((ctx: FlowModelContext) => StepParam | Promise<StepParam>);
113
+ enableTitle?: boolean;
114
+ divider?: 'top' | 'bottom';
112
115
  }
113
116
 
114
117
  export interface IModelComponentProps {
@@ -134,6 +137,8 @@ export enum ActionScene {
134
137
  BLOCK_LINKAGE_RULES = 1,
135
138
  /** 表单字段级联动规则可用 */
136
139
  FIELD_LINKAGE_RULES,
140
+ /** 子表单字段级联动规则可用 */
141
+ SUB_FORM_FIELD_LINKAGE_RULES,
137
142
  /** 详情字段级联动规则可用 */
138
143
  DETAILS_FIELD_LINKAGE_RULES,
139
144
  /** 按钮级联动规则可用 */
@@ -157,6 +162,36 @@ export interface ActionDefinition<TModel extends FlowModel = FlowModel, TCtx ext
157
162
  uiMode?: StepUIMode | ((ctx: FlowRuntimeContext<TModel>) => StepUIMode | Promise<StepUIMode>);
158
163
  scene?: ActionScene | ActionScene[];
159
164
  sort?: number;
165
+ /**
166
+ * Whether the step/action requires params to be configured before use.
167
+ */
168
+ paramsRequired?: boolean;
169
+ /**
170
+ * Whether to hide this step/action from settings menus.
171
+ * - Supports static boolean and dynamic decision based on runtime context.
172
+ * - StepDefinition.hideInSettings can override the ActionDefinition value.
173
+ */
174
+ hideInSettings?: boolean | ((ctx: TCtx) => boolean | Promise<boolean>);
175
+ /**
176
+ * 在执行 Action 前为 ctx 定义临时属性。
177
+ * - 仅支持 PropertyOptions 形态(例如:{ foo: { value: 5 } });
178
+ * - 或函数形式(接收 ctx,返回 PropertyOptions 对象;支持 Promise)。
179
+ */
180
+ defineProperties?:
181
+ | Record<string, PropertyOptions>
182
+ | ((ctx: TCtx) => Record<string, PropertyOptions> | Promise<Record<string, PropertyOptions>>);
183
+ /**
184
+ * 在执行 Action 前为 ctx 定义临时方法。
185
+ * - 支持 JSON 形式(对象的值应为函数)
186
+ * - 或函数形式(接收 ctx,返回方法对象;支持 Promise)
187
+ */
188
+ defineMethods?:
189
+ | Record<string, (this: TCtx, ...args: any[]) => any>
190
+ | ((
191
+ ctx: TCtx,
192
+ ) =>
193
+ | Record<string, (this: TCtx, ...args: any[]) => any>
194
+ | Promise<Record<string, (this: TCtx, ...args: any[]) => any>>);
160
195
  }
161
196
 
162
197
  /**
@@ -178,12 +213,47 @@ export type FlowEventName =
178
213
  // fallback to any string for extensibility
179
214
  | (string & {});
180
215
 
216
+ /**
217
+ * 事件流的执行时机(phase)。
218
+ *
219
+ * 说明:
220
+ * - 缺省(phase 未配置)表示保持现有行为;
221
+ * - 当配置了 phase 时,运行时会将其映射为 `scheduleModelOperation` 的 `when` 锚点;
222
+ * - phase 同时适用于动态事件流(实例级)与静态流(内置)。
223
+ */
224
+ export type FlowEventPhase =
225
+ | 'beforeAllFlows'
226
+ | 'afterAllFlows'
227
+ | 'beforeFlow'
228
+ | 'afterFlow'
229
+ | 'beforeStep'
230
+ | 'afterStep';
231
+
181
232
  /**
182
233
  * Flow 事件类型(供 FlowDefinitionOptions.on 使用)。
183
234
  */
184
235
  export type FlowEvent<TModel extends FlowModel = FlowModel> =
185
236
  | FlowEventName
186
- | { eventName: FlowEventName; defaultParams?: Record<string, any> };
237
+ | {
238
+ eventName: FlowEventName;
239
+ defaultParams?: Record<string, any>;
240
+ /** 动态事件流的执行时机(默认 beforeAllFlows) */
241
+ phase?: FlowEventPhase;
242
+ /** phase 为 beforeFlow/afterFlow/beforeStep/afterStep 时使用 */
243
+ flowKey?: string;
244
+ /** phase 为 beforeStep/afterStep 时使用 */
245
+ stepKey?: string;
246
+ };
247
+
248
+ /**
249
+ * 事件分发选项。
250
+ */
251
+ export interface DispatchEventOptions {
252
+ /** 是否顺序执行(默认并行) */
253
+ sequential?: boolean;
254
+ /** 是否使用缓存(默认 false;beforeRender 的默认值为 true,可覆盖) */
255
+ useCache?: boolean;
256
+ }
187
257
 
188
258
  /**
189
259
  * 事件定义:用于事件注册表(全局/模型类级)。
@@ -199,7 +269,7 @@ export type StepUIMode =
199
269
  | 'embed'
200
270
  // | 'switch'
201
271
  // | 'select'
202
- | { type?: 'dialog' | 'drawer' | 'embed'; props?: Record<string, any> };
272
+ | { type?: 'dialog' | 'drawer' | 'embed' | 'select' | 'switch'; props?: Record<string, any>; key?: string };
203
273
  // | { type: 'switch'; props?: Record<string, any> }
204
274
  // | { type: 'select'; props?: Record<string, any> }
205
275
 
@@ -218,8 +288,6 @@ export interface StepDefinition<TModel extends FlowModel = FlowModel>
218
288
  // Step configuration
219
289
  // `preset: true` 的 step params 需要在创建时填写,没有标记的可以创建模型后再填写。
220
290
  preset?: boolean;
221
- paramsRequired?: boolean; // Optional: whether the step params are required, will open the config dialog before adding the model
222
- hideInSettings?: boolean; // Optional: whether to hide the step in the settings menu
223
291
  uiMode?: StepUIMode | ((ctx: FlowRuntimeContext<TModel>) => StepUIMode | Promise<StepUIMode>);
224
292
  }
225
293
 
@@ -278,6 +346,18 @@ export type ParamObject = {
278
346
  */
279
347
  export type RegisteredModelClassName = string;
280
348
 
349
+ /**
350
+ * resolveUse 返回类型:可返回目标 use,或 { use, stop } 包含中断标志。
351
+ */
352
+ export type ResolveUseResult =
353
+ | RegisteredModelClassName
354
+ | ModelConstructor
355
+ | {
356
+ use: RegisteredModelClassName | ModelConstructor;
357
+ /** 标记是否终止后续 resolveUse 链;默认 false(继续解析) */
358
+ stop?: boolean;
359
+ };
360
+
281
361
  /**
282
362
  * Options for creating a model instance
283
363
  */
@@ -300,6 +380,7 @@ export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
300
380
  save(model: T, options?: { onlyStepParams?: boolean }): Promise<Record<string, any>>;
301
381
  destroy(uid: string): Promise<boolean>;
302
382
  move(sourceId: string, targetId: string, position: 'before' | 'after'): Promise<void>;
383
+ duplicate(uid: string): Promise<Record<string, any> | null>;
303
384
  }
304
385
 
305
386
  /**
@@ -419,7 +500,7 @@ export type FlowModelMeta =
419
500
  * 是否在菜单中隐藏该模型类
420
501
  * @default false
421
502
  */
422
- hide?: boolean;
503
+ hide?: boolean | ((context: FlowModelContext) => boolean);
423
504
  eventList?: { label: string; value: string }[]; // 支持的事件列表
424
505
  };
425
506
 
@@ -0,0 +1,51 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { describe, expect, it } from 'vitest';
11
+ import { createCollectionContextMeta } from '../createCollectionContextMeta';
12
+ import { FlowEngine } from '../../flowEngine';
13
+ import { CollectionFieldInterfaceManager } from '../../../../client/src/data-source/collection-field-interface/CollectionFieldInterfaceManager';
14
+
15
+ describe('createCollectionContextMeta', () => {
16
+ it('filters association sub fields when includeNonFilterable is false', async () => {
17
+ const engine = new FlowEngine();
18
+ const dm = engine.dataSourceManager as any;
19
+ dm.collectionFieldInterfaceManager = new CollectionFieldInterfaceManager([], {}, dm);
20
+ engine.context.defineProperty('app', { value: { dataSourceManager: dm } });
21
+ const ds = dm.getDataSource('main')!;
22
+
23
+ ds.addCollection({
24
+ name: 'users',
25
+ fields: [
26
+ { name: 'id', type: 'integer', interface: 'number', filterable: true },
27
+ { name: 'email', type: 'string', interface: 'text', filterable: true },
28
+ { name: 'nickname', type: 'string', interface: 'text' }, // 未声明 filterable
29
+ ],
30
+ });
31
+
32
+ ds.addCollection({
33
+ name: 'posts',
34
+ fields: [
35
+ { name: 'title', type: 'string', interface: 'text', filterable: true },
36
+ { name: 'author', type: 'belongsTo', target: 'users', interface: 'm2o', filterable: true },
37
+ ],
38
+ });
39
+
40
+ const posts = ds.getCollection('posts')!;
41
+ const metaFactory = createCollectionContextMeta(posts, 'Posts', false);
42
+ const meta = await metaFactory();
43
+ const props = await (meta?.properties as any)?.();
44
+ const authorMeta: any = props?.author;
45
+ const authorFields = await authorMeta?.properties?.();
46
+
47
+ expect(authorFields).toBeTruthy();
48
+ expect(authorFields).toHaveProperty('email');
49
+ expect(authorFields).not.toHaveProperty('nickname');
50
+ });
51
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { describe, test, expect } from 'vitest';
11
+ import { FlowEngine } from '../../flowEngine';
12
+ import { FlowModel } from '../../models/flowModel';
13
+ import { isBeforeRenderFlow } from '../index';
14
+
15
+ describe('utils/isBeforeRenderFlow', () => {
16
+ test('identifies beforeRender by on string', () => {
17
+ const engine = new FlowEngine();
18
+ class M extends FlowModel {}
19
+ engine.registerModels({ M });
20
+ const m = engine.createModel({ use: 'M' });
21
+ m.registerFlow('A', { on: 'beforeRender', steps: {} });
22
+ const flow = m.flowRegistry.getFlow('A')!;
23
+ expect(isBeforeRenderFlow(flow)).toBe(true);
24
+ });
25
+
26
+ test('identifies beforeRender by on object', () => {
27
+ const engine = new FlowEngine();
28
+ class M extends FlowModel {}
29
+ engine.registerModels({ M });
30
+ const m = engine.createModel({ use: 'M' });
31
+ m.registerFlow('B', { on: { eventName: 'beforeRender' }, steps: {} });
32
+ const flow = m.flowRegistry.getFlow('B')!;
33
+ expect(isBeforeRenderFlow(flow)).toBe(true);
34
+ });
35
+
36
+ test('treats missing on and non-manual as beforeRender', () => {
37
+ const engine = new FlowEngine();
38
+ class M extends FlowModel {}
39
+ engine.registerModels({ M });
40
+ const m = engine.createModel({ use: 'M' });
41
+ m.registerFlow('C', { steps: {} });
42
+ const flow = m.flowRegistry.getFlow('C')!;
43
+ expect(isBeforeRenderFlow(flow)).toBe(true);
44
+ });
45
+
46
+ test('manual flow is not beforeRender when on is missing', () => {
47
+ const engine = new FlowEngine();
48
+ class M extends FlowModel {}
49
+ engine.registerModels({ M });
50
+ const m = engine.createModel({ use: 'M' });
51
+ m.registerFlow('D', { manual: true, steps: {} });
52
+ const flow = m.flowRegistry.getFlow('D')!;
53
+ expect(isBeforeRenderFlow(flow)).toBe(false);
54
+ });
55
+
56
+ test('non-beforeRender event is not beforeRender', () => {
57
+ const engine = new FlowEngine();
58
+ class M extends FlowModel {}
59
+ engine.registerModels({ M });
60
+ const m = engine.createModel({ use: 'M' });
61
+ m.registerFlow('E', { on: { eventName: 'click' }, steps: {} });
62
+ const flow = m.flowRegistry.getFlow('E')!;
63
+ expect(isBeforeRenderFlow(flow)).toBe(false);
64
+ });
65
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { describe, it, expect } from 'vitest';
11
+ import { compileRunJs } from '../../utils/jsxTransform';
12
+
13
+ describe('compileRunJs', () => {
14
+ it('returns original code when no JSX is present', async () => {
15
+ const src = `const a = 1; const b = a + 1;`;
16
+ const out = await compileRunJs(src);
17
+ expect(out).toBe(src);
18
+ });
19
+
20
+ it('transforms JSX when sucrase is available (skip if missing)', async () => {
21
+ const src = `ctx.render(<div className="x">hi</div>);`;
22
+
23
+ // Try to import sucrase to decide if this environment has it installed
24
+ const hasSucrase = await import('sucrase').then(() => true).catch(() => false);
25
+
26
+ const out = await compileRunJs(src);
27
+
28
+ if (!hasSucrase) {
29
+ // Environment without sucrase: current implementation falls back to original code
30
+ expect(out).toBe(src);
31
+ return;
32
+ }
33
+
34
+ // sucrase available: output should contain React.createElement mapping
35
+ expect(out).not.toBe(src);
36
+ expect(out).toMatch(/ctx\.React\.createElement/);
37
+ });
38
+ });
@@ -491,6 +491,46 @@ describe('resolveExpressions', () => {
491
491
  ],
492
492
  });
493
493
  });
494
+
495
+ test('should resolve dot-only path with dashed keys', async () => {
496
+ ctx.defineProperty('formValues', {
497
+ value: {
498
+ 'oho-test': {
499
+ 'o2m-users': [1, 2],
500
+ },
501
+ },
502
+ });
503
+
504
+ const params = '{{ctx.formValues.oho-test.o2m-users}}';
505
+
506
+ const result = await resolveExpressions(params, ctx);
507
+
508
+ expect(result).toEqual([1, 2]);
509
+ });
510
+
511
+ test('should resolve dashed keys inside template strings', async () => {
512
+ ctx.defineProperty('formValues', {
513
+ value: {
514
+ 'oho-test': {
515
+ 'o2m-users': 'X',
516
+ },
517
+ },
518
+ });
519
+
520
+ const params = 'prefix {{ctx.formValues.oho-test.o2m-users}} suffix';
521
+
522
+ const result = await resolveExpressions(params, ctx);
523
+
524
+ expect(result).toEqual('prefix X suffix');
525
+ });
526
+
527
+ test('should not treat subtraction as dashed key path', async () => {
528
+ const params = '{{ctx.aa.bb-ctx.cc}}';
529
+
530
+ const result = await resolveExpressions(params, ctx);
531
+
532
+ expect(result).toEqual(5);
533
+ });
494
534
  });
495
535
 
496
536
  // 测试高级功能:多表达式模板字符串