@nocobase/flow-engine 2.0.0-alpha.3 → 2.0.0-alpha.30

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 (418) 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/components/FieldModelRenderer.js +10 -4
  9. package/lib/components/FieldSkeleton.d.ts +10 -0
  10. package/lib/components/FieldSkeleton.js +64 -0
  11. package/lib/components/FlowContextSelector.js +7 -2
  12. package/lib/components/FlowModelRenderer.d.ts +2 -5
  13. package/lib/components/FlowModelRenderer.js +16 -47
  14. package/lib/components/FormItem.js +5 -1
  15. package/lib/{runjs-context/snippets/global/requireAsync.snippet.d.ts → components/dnd/findModelUidPosition.d.ts} +4 -7
  16. package/lib/{runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js → components/dnd/findModelUidPosition.js} +23 -19
  17. package/lib/components/dnd/gridDragPlanner.d.ts +130 -0
  18. package/lib/components/dnd/gridDragPlanner.js +497 -0
  19. package/lib/components/dnd/index.d.ts +2 -2
  20. package/lib/components/dnd/index.js +5 -5
  21. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
  22. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
  23. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
  24. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
  25. package/lib/components/variables/VariableInput.js +16 -2
  26. package/lib/components/variables/VariableTag.js +43 -2
  27. package/lib/components/variables/types.d.ts +2 -0
  28. package/lib/data-source/index.d.ts +12 -4
  29. package/lib/data-source/index.js +19 -13
  30. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  31. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  32. package/lib/executor/FlowExecutor.d.ts +4 -5
  33. package/lib/executor/FlowExecutor.js +135 -100
  34. package/lib/flowContext.d.ts +33 -5
  35. package/lib/flowContext.js +193 -76
  36. package/lib/flowEngine.d.ts +8 -1
  37. package/lib/flowEngine.js +18 -6
  38. package/lib/flowSettings.d.ts +2 -1
  39. package/lib/flowSettings.js +12 -8
  40. package/lib/hooks/useApplyAutoFlows.js +2 -1
  41. package/lib/index.d.ts +7 -1
  42. package/lib/index.js +32 -3
  43. package/lib/locale/en-US.json +4 -2
  44. package/lib/locale/index.d.ts +4 -0
  45. package/lib/locale/zh-CN.json +4 -2
  46. package/lib/models/CollectionFieldModel.d.ts +2 -0
  47. package/lib/models/CollectionFieldModel.js +43 -3
  48. package/lib/models/flowModel.d.ts +28 -29
  49. package/lib/models/flowModel.js +114 -92
  50. package/lib/models/forkFlowModel.d.ts +4 -4
  51. package/lib/models/forkFlowModel.js +32 -8
  52. package/lib/provider.d.ts +3 -1
  53. package/lib/provider.js +7 -5
  54. package/lib/resources/multiRecordResource.js +2 -0
  55. package/lib/resources/singleRecordResource.js +1 -0
  56. package/lib/resources/sqlResource.d.ts +1 -0
  57. package/lib/resources/sqlResource.js +20 -24
  58. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  59. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  60. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  61. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  62. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  63. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  64. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  65. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  66. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  67. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  68. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  69. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  70. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  71. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  72. package/lib/runjs-context/contexts/base.d.ts +9 -0
  73. package/lib/runjs-context/contexts/base.js +183 -0
  74. package/lib/runjs-context/helpers.d.ts +5 -2
  75. package/lib/runjs-context/helpers.js +36 -27
  76. package/lib/runjs-context/registry.d.ts +7 -4
  77. package/lib/runjs-context/registry.js +10 -42
  78. package/lib/runjs-context/setup.d.ts +9 -0
  79. package/lib/runjs-context/setup.js +82 -0
  80. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  81. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  82. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  83. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  84. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  85. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  86. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  87. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  88. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  89. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  90. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  91. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  92. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  93. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  94. package/lib/runjs-context/snippets/index.d.ts +14 -3
  95. package/lib/runjs-context/snippets/index.js +161 -40
  96. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  97. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  98. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  99. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  100. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  101. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  102. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  103. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  104. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  105. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  106. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  107. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  109. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  111. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  113. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  114. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  115. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  116. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  117. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  118. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  119. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  120. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  121. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  122. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  123. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  124. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  125. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  126. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  127. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  128. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  129. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  130. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  131. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  132. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  133. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  134. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  135. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  136. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  137. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  138. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  139. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  140. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  141. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  142. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  143. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  144. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  145. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  146. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  147. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  148. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  149. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  150. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  151. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  152. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  153. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  154. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  155. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  156. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  157. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  158. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  159. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  160. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  161. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  162. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  163. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  164. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  165. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  166. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  167. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  168. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  169. package/lib/runjs-context/snippets/types.d.ts +9 -1
  170. package/lib/types.d.ts +28 -3
  171. package/lib/types.js +4 -3
  172. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  173. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  174. package/lib/utils/createEphemeralContext.d.ts +13 -0
  175. package/lib/utils/createEphemeralContext.js +140 -0
  176. package/lib/utils/index.d.ts +3 -2
  177. package/lib/utils/index.js +5 -2
  178. package/lib/utils/jsxTransform.d.ts +15 -0
  179. package/lib/utils/jsxTransform.js +68 -0
  180. package/lib/utils/params-resolvers.js +3 -3
  181. package/lib/utils/safeGlobals.d.ts +5 -3
  182. package/lib/utils/safeGlobals.js +40 -0
  183. package/lib/utils/schema-utils.js +2 -2
  184. package/lib/utils/serverContextParams.d.ts +1 -0
  185. package/lib/utils/variablesParams.d.ts +9 -5
  186. package/lib/utils/variablesParams.js +47 -36
  187. package/lib/views/PageComponent.js +2 -1
  188. package/lib/views/createViewMeta.d.ts +29 -1
  189. package/lib/views/createViewMeta.js +338 -72
  190. package/lib/views/index.d.ts +1 -0
  191. package/lib/views/index.js +3 -0
  192. package/lib/views/useDialog.d.ts +8 -8
  193. package/lib/views/useDialog.js +8 -7
  194. package/lib/views/useDrawer.d.ts +8 -8
  195. package/lib/views/useDrawer.js +40 -26
  196. package/lib/views/usePage.d.ts +8 -8
  197. package/lib/views/usePage.js +8 -7
  198. package/package.json +5 -3
  199. package/src/BlockScopedFlowEngine.ts +86 -0
  200. package/src/FlowContextProvider.tsx +4 -2
  201. package/src/JSRunner.ts +3 -0
  202. package/src/ViewScopedFlowEngine.ts +1 -1
  203. package/src/__tests__/JSRunner.test.ts +62 -53
  204. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  205. package/src/__tests__/createViewMeta.popup.test.ts +132 -0
  206. package/src/__tests__/flow-engine.test.ts +3 -0
  207. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  208. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  209. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  210. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  211. package/src/__tests__/runjsContext.test.ts +216 -35
  212. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  213. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  214. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  215. package/src/__tests__/runjsLocales.test.ts +36 -0
  216. package/src/__tests__/runjsRuntimeFeatures.test.ts +449 -0
  217. package/src/__tests__/runjsSnippets.test.ts +140 -0
  218. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  219. package/src/components/DynamicFlowsEditor.tsx +3 -4
  220. package/src/components/FieldModelRenderer.tsx +16 -5
  221. package/src/components/FieldSkeleton.tsx +27 -0
  222. package/src/components/FlowContextSelector.tsx +6 -2
  223. package/src/components/FlowModelRenderer.tsx +30 -78
  224. package/src/components/FormItem.tsx +8 -1
  225. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +5 -5
  226. package/src/components/__tests__/gridDragPlanner.test.ts +494 -0
  227. package/src/components/dnd/README.md +149 -0
  228. package/src/components/dnd/findModelUidPosition.ts +26 -0
  229. package/src/components/dnd/gridDragPlanner.ts +659 -0
  230. package/src/components/dnd/index.tsx +3 -3
  231. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
  232. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
  233. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
  234. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  235. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +424 -0
  236. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
  237. package/src/components/variables/VariableInput.tsx +22 -2
  238. package/src/components/variables/VariableTag.tsx +54 -2
  239. package/src/components/variables/types.ts +2 -0
  240. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  241. package/src/data-source/index.ts +17 -11
  242. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  243. package/src/executor/FlowExecutor.ts +178 -121
  244. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  245. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  246. package/src/flowContext.ts +266 -97
  247. package/src/flowEngine.ts +21 -6
  248. package/src/flowSettings.ts +9 -4
  249. package/src/hooks/useApplyAutoFlows.ts +3 -1
  250. package/src/index.ts +12 -1
  251. package/src/locale/en-US.json +4 -2
  252. package/src/locale/zh-CN.json +4 -2
  253. package/src/models/CollectionFieldModel.tsx +43 -4
  254. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +4 -4
  255. package/src/models/__tests__/flowModel.test.ts +234 -111
  256. package/src/models/__tests__/forkFlowModel.test.ts +22 -7
  257. package/src/models/flowModel.tsx +149 -125
  258. package/src/models/forkFlowModel.ts +41 -8
  259. package/src/provider.tsx +10 -7
  260. package/src/resources/multiRecordResource.ts +2 -0
  261. package/src/resources/singleRecordResource.ts +1 -0
  262. package/src/resources/sqlResource.ts +20 -25
  263. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  264. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  265. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  266. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  267. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  268. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  269. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  270. package/src/runjs-context/contexts/base.ts +171 -0
  271. package/src/runjs-context/helpers.ts +32 -30
  272. package/src/runjs-context/registry.ts +16 -47
  273. package/src/runjs-context/setup.ts +51 -0
  274. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  275. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  276. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  277. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  278. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  279. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  280. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  281. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  282. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  283. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  284. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  285. package/src/runjs-context/snippets/index.ts +177 -39
  286. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  287. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  288. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  289. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  290. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  291. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  292. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  293. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  294. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  295. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  296. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  297. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  298. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  299. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  300. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  301. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  302. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  303. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  304. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  305. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  306. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  307. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  308. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  309. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  310. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  311. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  312. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  313. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  314. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  315. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  316. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  317. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  318. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  319. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  320. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  321. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  322. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  323. package/src/runjs-context/snippets/types.ts +5 -1
  324. package/src/types.ts +34 -0
  325. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  326. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  327. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  328. package/src/utils/createEphemeralContext.ts +142 -0
  329. package/src/utils/index.ts +2 -2
  330. package/src/utils/jsxTransform.ts +39 -0
  331. package/src/utils/params-resolvers.ts +2 -2
  332. package/src/utils/safeGlobals.ts +49 -3
  333. package/src/utils/schema-utils.ts +1 -1
  334. package/src/utils/serverContextParams.ts +1 -0
  335. package/src/utils/variablesParams.ts +50 -38
  336. package/src/views/PageComponent.tsx +1 -1
  337. package/src/views/createViewMeta.ts +393 -70
  338. package/src/views/index.tsx +1 -0
  339. package/src/views/useDialog.tsx +12 -10
  340. package/src/views/useDrawer.tsx +60 -36
  341. package/src/views/usePage.tsx +13 -10
  342. package/lib/components/dnd/getMousePositionOnElement.d.ts +0 -50
  343. package/lib/components/dnd/getMousePositionOnElement.js +0 -95
  344. package/lib/components/dnd/moveBlock.d.ts +0 -33
  345. package/lib/components/dnd/moveBlock.js +0 -302
  346. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  347. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  348. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  349. package/lib/runjs-context/index.d.ts +0 -19
  350. package/lib/runjs-context/index.js +0 -57
  351. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  352. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  353. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  354. package/lib/runjs-context/snippets/global/api-request-post.snippet.js +0 -42
  355. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  356. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  357. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  358. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  359. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  360. package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +0 -44
  361. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  362. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  363. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  364. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  365. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  366. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  367. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  368. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  369. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  370. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  371. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  372. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  373. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  374. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  375. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  376. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  377. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  378. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  379. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  380. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  381. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  382. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  383. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  384. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  385. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  386. package/src/components/dnd/getMousePositionOnElement.ts +0 -115
  387. package/src/components/dnd/moveBlock.ts +0 -379
  388. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  389. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  390. package/src/runjs-context/index.ts +0 -20
  391. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  392. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  393. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  394. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  395. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  396. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  397. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  398. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  399. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  400. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  401. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  402. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  403. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  404. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  405. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  406. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  407. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  408. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  409. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  410. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  411. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  412. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  413. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  414. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  415. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  416. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  417. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  418. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -11,14 +11,16 @@ import { ISchema } from '@formily/json-schema';
11
11
  import { observable } from '@formily/reactive';
12
12
  import { APIClient } from '@nocobase/sdk';
13
13
  import type { Router } from '@remix-run/router';
14
- import * as antd from 'antd';
15
14
  import { MessageInstance } from 'antd/es/message/interface';
15
+ import * as antd from 'antd';
16
16
  import type { HookAPI } from 'antd/es/modal/useModal';
17
17
  import { NotificationInstance } from 'antd/es/notification/interface';
18
18
  import _ from 'lodash';
19
19
  import pino from 'pino';
20
20
  import qs from 'qs';
21
21
  import React, { createRef } from 'react';
22
+ import * as ReactDOMClient from 'react-dom/client';
23
+ import { ElementProxy } from './ElementProxy';
22
24
  import type { Location } from 'react-router-dom';
23
25
  import { ACL } from './acl/Acl';
24
26
  import { ContextPathProxy } from './ContextPathProxy';
@@ -26,21 +28,11 @@ import { DataSource, DataSourceManager } from './data-source';
26
28
  import { FlowEngine } from './flowEngine';
27
29
  import { FlowI18n } from './flowI18n';
28
30
  import { JSRunner, JSRunnerOptions } from './JSRunner';
29
- import { createJSRunnerWithVersion } from './runjs-context';
30
- import { FlowModel, ForkFlowModel } from './models';
31
- import {
32
- APIResource,
33
- BaseRecordResource,
34
- FlowResource,
35
- FlowSQLRepository,
36
- MultiRecordResource,
37
- SingleRecordResource,
38
- SQLResource,
39
- } from './resources';
31
+ import type { FlowModel } from './models/flowModel';
32
+ import type { ForkFlowModel } from './models/forkFlowModel';
33
+ import { FlowResource, FlowSQLRepository } from './resources';
40
34
  import type { ActionDefinition, EventDefinition, ResourceType } from './types';
41
35
  import {
42
- createSafeDocument,
43
- createSafeWindow,
44
36
  escapeT,
45
37
  extractPropertyPath,
46
38
  extractUsedVariablePaths,
@@ -53,6 +45,8 @@ import { enqueueVariablesResolve, JSONValue } from './utils/params-resolvers';
53
45
  import type { RecordRef } from './utils/serverContextParams';
54
46
  import { buildServerContextParams as _buildServerContextParams } from './utils/serverContextParams';
55
47
  import { FlowView, FlowViewer } from './views/FlowView';
48
+ import { RunJSContextRegistry, getModelClassName } from './runjs-context/registry';
49
+ import { createEphemeralContext } from './utils/createEphemeralContext';
56
50
 
57
51
  // Helper: detect a RecordRef-like object
58
52
  function isRecordRefLike(val: any): boolean {
@@ -892,38 +886,11 @@ export class FlowContext {
892
886
  }
893
887
  }
894
888
 
895
- export class FlowRunjsContext extends FlowContext {
896
- constructor(delegate: FlowContext) {
897
- super();
898
- this.addDelegate(delegate);
899
- // Expose React and antd only within runjs context
900
- // This keeps the scope minimal while enabling React/AntD rendering in scripts
901
- this.defineProperty('React', { value: React });
902
- this.defineProperty('antd', { value: antd });
903
- this.defineMethod(
904
- 'dispatchModelEvent',
905
- async (modelOrUid: FlowModel | string, eventName: string, inputArgs?: Record<string, any>) => {
906
- let model: FlowModel | null = null;
907
- if (typeof modelOrUid === 'string') {
908
- model = await this.engine.loadModel({ uid: modelOrUid });
909
- } else if (modelOrUid instanceof FlowModel) {
910
- model = modelOrUid;
911
- }
912
- if (model) {
913
- model.context.addDelegate(this);
914
- model.dispatchEvent(eventName, { navigation: false, ...this.model?.['getInputArgs']?.(), ...inputArgs });
915
- } else {
916
- this.message.error(this.t('Model with ID {{uid}} not found', { uid: modelOrUid }));
917
- }
918
- },
919
- );
920
- }
921
- }
922
-
923
889
  class BaseFlowEngineContext extends FlowContext {
924
890
  declare router: Router;
925
891
  declare dataSourceManager: DataSourceManager;
926
892
  declare requireAsync: (url: string) => Promise<any>;
893
+ declare importAsync: (url: string) => Promise<any>;
927
894
  declare createJSRunner: (options?: JSRunnerOptions) => JSRunner;
928
895
  /**
929
896
  * @deprecated use `resolveJsonTemplate` instead
@@ -931,7 +898,6 @@ class BaseFlowEngineContext extends FlowContext {
931
898
  declare renderJson: (template: JSONValue) => Promise<any>;
932
899
  declare resolveJsonTemplate: (template: JSONValue) => Promise<any>;
933
900
  declare runjs: (code: string, variables?: Record<string, any>, options?: JSRunnerOptions) => Promise<any>;
934
- declare copyToClipboard: (text: string) => Promise<void>;
935
901
  declare getAction: <TModel extends FlowModel = FlowModel, TCtx extends FlowContext = FlowContext>(
936
902
  name: string,
937
903
  ) => ActionDefinition<TModel, TCtx> | undefined;
@@ -1005,10 +971,10 @@ export class FlowEngineContext extends BaseFlowEngineContext {
1005
971
  });
1006
972
  this.defineMethod('runjs', async (code, variables, options?: JSRunnerOptions) => {
1007
973
  const mergedGlobals = { ...(options?.globals || {}), ...(variables || {}) };
1008
- const runner = this.createJSRunner({
974
+ const runner = (await (this as any).createJSRunner({
1009
975
  ...(options || {}),
1010
976
  globals: mergedGlobals,
1011
- });
977
+ })) as JSRunner;
1012
978
  return runner.run(code);
1013
979
  });
1014
980
  this.defineMethod('renderJson', function (template: any) {
@@ -1218,50 +1184,60 @@ export class FlowEngineContext extends BaseFlowEngineContext {
1218
1184
  );
1219
1185
  });
1220
1186
  });
1221
- this.defineMethod('createJSRunner', function (options?: JSRunnerOptions) {
1222
- // return createJSRunnerWithVersion.call(this, options as any);
1223
- const runCtx = new FlowRunjsContext(this.createProxy());
1224
- return new JSRunner({
1225
- ...options,
1226
- globals: {
1227
- ctx: runCtx,
1228
- window: createSafeWindow(),
1229
- document: createSafeDocument(),
1230
- ...options?.globals,
1231
- },
1232
- });
1233
- });
1234
- // 复制文本到剪贴板(优先使用 Clipboard API,降级到 execCommand)
1235
- this.defineMethod('copyToClipboard', async (text: string) => {
1236
- const content = String(text ?? '');
1237
- try {
1238
- if (typeof navigator !== 'undefined' && navigator.clipboard && navigator.clipboard.writeText) {
1239
- await navigator.clipboard.writeText(content);
1240
- return;
1241
- }
1242
- } catch (e) {
1243
- // 忽略,尝试降级方案
1187
+ // 动态按 URL 加载 ESM 模块
1188
+ // - 使用 Vite / Webpack ignore 注释,避免被预打包或重写
1189
+ // - 返回模块命名空间对象(包含 default 与命名导出)
1190
+ this.defineMethod('importAsync', async (url: string) => {
1191
+ if (!url || typeof url !== 'string') {
1192
+ throw new Error('invalid url');
1244
1193
  }
1245
-
1246
- // 降级方案:创建临时 textarea + execCommand('copy')
1247
- return new Promise<void>((resolve, reject) => {
1194
+ const u = url.trim();
1195
+ const g = globalThis as any;
1196
+ g.__nocobaseImportAsyncCache = g.__nocobaseImportAsyncCache || new Map<string, Promise<any>>();
1197
+ const cache: Map<string, Promise<any>> = g.__nocobaseImportAsyncCache;
1198
+ if (cache.has(u)) return cache.get(u)!;
1199
+ // 尝试使用原生 dynamic import(加上 vite/webpack 的 ignore 注释)
1200
+ const nativeImport = () => import(/* @vite-ignore */ /* webpackIgnore: true */ u);
1201
+ // 兜底方案:通过 eval 在运行时构造 import,避免被打包器接管
1202
+ const evalImport = () => {
1203
+ const importer = (0, eval)('u => import(u)');
1204
+ return importer(u);
1205
+ };
1206
+ const p = (async () => {
1248
1207
  try {
1249
- const ta = document.createElement('textarea');
1250
- ta.value = content;
1251
- ta.setAttribute('readonly', '');
1252
- ta.style.position = 'fixed';
1253
- ta.style.top = '-9999px';
1254
- document.body.appendChild(ta);
1255
- ta.focus();
1256
- ta.select();
1257
- const ok = document.execCommand('copy');
1258
- document.body.removeChild(ta);
1259
- if (ok) resolve();
1260
- else reject(new Error('execCommand copy failed'));
1261
- } catch (err) {
1262
- reject(err);
1208
+ return await nativeImport();
1209
+ } catch (err: any) {
1210
+ // 常见于打包产物仍然拦截了 dynamic import 或开发态插件未识别 ignore 注释
1211
+ try {
1212
+ return await evalImport();
1213
+ } catch (err2) {
1214
+ throw err2 || err;
1215
+ }
1263
1216
  }
1264
- });
1217
+ })();
1218
+ cache.set(u, p);
1219
+ return p;
1220
+ });
1221
+ this.defineMethod('createJSRunner', async function (options?: JSRunnerOptions) {
1222
+ try {
1223
+ const mod: any = await import('./runjs-context/setup');
1224
+ if (typeof mod?.setupRunJSContexts === 'function') await mod.setupRunJSContexts();
1225
+ } catch (_) {
1226
+ // ignore if setup is not available
1227
+ }
1228
+ const version = (options?.version as any) || 'v1';
1229
+ const modelClass = getModelClassName(this);
1230
+ const Ctor =
1231
+ (RunJSContextRegistry.resolve(version, modelClass) as any) ||
1232
+ (RunJSContextRegistry.resolve(version, '*') as any) ||
1233
+ FlowRunJSContext;
1234
+ let runCtx: any;
1235
+ if (Ctor) {
1236
+ runCtx = new Ctor(this);
1237
+ }
1238
+ const globals: Record<string, any> = { ctx: runCtx, ...(options?.globals || {}) };
1239
+ const { timeoutMs } = options || {};
1240
+ return new JSRunner({ globals, timeoutMs });
1265
1241
  });
1266
1242
  // Helper: build server contextParams for variables:resolve
1267
1243
  this.defineMethod('buildServerContextParams', function (this: BaseFlowEngineContext, input?: any) {
@@ -1332,7 +1308,8 @@ export class FlowEngineContext extends BaseFlowEngineContext {
1332
1308
  'runAction',
1333
1309
  async function (this: BaseFlowEngineContext, actionName: string, params?: Record<string, any>) {
1334
1310
  const def = this.engine.getAction<FlowModel, FlowEngineContext>(actionName);
1335
- const ctx = this.createProxy() as unknown as FlowEngineContext;
1311
+ // 使用“临时作用域”上下文,避免将临时定义污染到引擎级上下文,并在创建时应用定义
1312
+ const ctx = await createEphemeralContext(this as unknown as FlowEngineContext, def);
1336
1313
  if (!def) {
1337
1314
  throw new Error(`Action '${actionName}' not found.`);
1338
1315
  }
@@ -1346,7 +1323,7 @@ export class FlowEngineContext extends BaseFlowEngineContext {
1346
1323
  }
1347
1324
  if (!useRawParams) {
1348
1325
  // 先服务端解析,再前端补齐
1349
- combinedParams = await (ctx as any).resolveJsonTemplate(combinedParams);
1326
+ combinedParams = await ctx.resolveJsonTemplate(combinedParams);
1350
1327
  }
1351
1328
 
1352
1329
  if (!def.handler) {
@@ -1369,12 +1346,25 @@ export class FlowEngineContext extends BaseFlowEngineContext {
1369
1346
  context: this.createProxy(),
1370
1347
  });
1371
1348
  });
1349
+ // Provide useResource in base engine context so RunJS can call it directly
1350
+ this.defineMethod(
1351
+ 'useResource',
1352
+ function (
1353
+ this: BaseFlowEngineContext,
1354
+ className: 'APIResource' | 'SingleRecordResource' | 'MultiRecordResource' | 'SQLResource',
1355
+ ) {
1356
+ if (this.has('resource')) return;
1357
+ this.defineProperty('resource', {
1358
+ get: () => this.createResource(className),
1359
+ });
1360
+ },
1361
+ );
1372
1362
  }
1373
1363
  }
1374
1364
 
1375
1365
  export class FlowModelContext extends BaseFlowModelContext {
1376
1366
  constructor(model: FlowModel) {
1377
- if (!(model instanceof FlowModel)) {
1367
+ if (!model || typeof model !== 'object') {
1378
1368
  throw new Error('Invalid FlowModel instance');
1379
1369
  }
1380
1370
  super();
@@ -1383,7 +1373,7 @@ export class FlowModelContext extends BaseFlowModelContext {
1383
1373
  this.engine.reactView.onRefReady(ref, cb, timeout);
1384
1374
  });
1385
1375
  this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
1386
- const runner = this.createJSRunner({
1376
+ const runner = await this.createJSRunner({
1387
1377
  globals: variables,
1388
1378
  version: options?.version,
1389
1379
  });
@@ -1392,10 +1382,12 @@ export class FlowModelContext extends BaseFlowModelContext {
1392
1382
  this.defineProperty('model', {
1393
1383
  value: model,
1394
1384
  });
1385
+ // 提供稳定的 ref 实例,确保渲染端与运行时上下文使用同一对象
1386
+ const stableRef = createRef<HTMLDivElement>();
1395
1387
  this.defineProperty('ref', {
1396
1388
  get: () => {
1397
1389
  this.model['_refCreated'] = true;
1398
- return createRef<HTMLDivElement>();
1390
+ return stableRef;
1399
1391
  },
1400
1392
  });
1401
1393
  this.defineMethod('openView', async function (uid: string, options) {
@@ -1475,7 +1467,8 @@ export class FlowModelContext extends BaseFlowModelContext {
1475
1467
  'runAction',
1476
1468
  async function (this: BaseFlowModelContext, actionName: string, params?: Record<string, any>) {
1477
1469
  const def = this.model.getAction<FlowModel, FlowModelContext>(actionName);
1478
- const ctx = this.createProxy() as unknown as FlowModelContext;
1470
+ // 使用“临时作用域”上下文,避免将临时定义污染到模型级上下文,并在创建时应用定义
1471
+ const ctx = await createEphemeralContext(this as unknown as FlowModelContext, def);
1479
1472
  if (!def) {
1480
1473
  throw new Error(`Action '${actionName}' not found.`);
1481
1474
  }
@@ -1488,7 +1481,7 @@ export class FlowModelContext extends BaseFlowModelContext {
1488
1481
  useRawParams = await useRawParams(ctx);
1489
1482
  }
1490
1483
  if (!useRawParams) {
1491
- combinedParams = await (ctx as any).resolveJsonTemplate(combinedParams);
1484
+ combinedParams = await ctx.resolveJsonTemplate(combinedParams);
1492
1485
  }
1493
1486
 
1494
1487
  if (!def.handler) {
@@ -1505,7 +1498,7 @@ export class FlowForkModelContext extends BaseFlowModelContext {
1505
1498
  public master: FlowModel,
1506
1499
  public fork: ForkFlowModel,
1507
1500
  ) {
1508
- if (!(master instanceof FlowModel)) {
1501
+ if (!master || typeof master !== 'object') {
1509
1502
  throw new Error('Invalid FlowModel instance');
1510
1503
  }
1511
1504
  super();
@@ -1516,14 +1509,16 @@ export class FlowForkModelContext extends BaseFlowModelContext {
1516
1509
  this.defineProperty('model', {
1517
1510
  get: () => this.fork,
1518
1511
  });
1512
+ // 提供稳定的 ref 实例,确保渲染端与运行时上下文使用同一对象
1513
+ const stableRef = createRef<HTMLDivElement>();
1519
1514
  this.defineProperty('ref', {
1520
1515
  get: () => {
1521
1516
  this.fork['_refCreated'] = true;
1522
- return createRef<HTMLDivElement>();
1517
+ return stableRef;
1523
1518
  },
1524
1519
  });
1525
1520
  this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
1526
- const runner = this.createJSRunner({
1521
+ const runner = await this.createJSRunner({
1527
1522
  globals: variables,
1528
1523
  version: options?.version,
1529
1524
  });
@@ -1584,7 +1579,7 @@ export class FlowRuntimeContext<
1584
1579
  this.engine.reactView.onRefReady(ref, cb, timeout);
1585
1580
  });
1586
1581
  this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
1587
- const runner = this.createJSRunner({
1582
+ const runner = await this.createJSRunner({
1588
1583
  globals: variables,
1589
1584
  version: options?.version,
1590
1585
  });
@@ -1637,3 +1632,177 @@ export class FlowRuntimeContext<
1637
1632
 
1638
1633
  // 类型别名,方便使用
1639
1634
  export type FlowSettingsContext<TModel extends FlowModel = FlowModel> = FlowRuntimeContext<TModel, 'settings'>;
1635
+
1636
+ export type RunJSDocCompletionDoc = {
1637
+ insertText?: string;
1638
+ };
1639
+
1640
+ export type RunJSDocPropertyDoc =
1641
+ | string
1642
+ | {
1643
+ description?: string;
1644
+ detail?: string;
1645
+ type?: string;
1646
+ examples?: string[];
1647
+ completion?: RunJSDocCompletionDoc;
1648
+ properties?: Record<string, RunJSDocPropertyDoc>;
1649
+ };
1650
+
1651
+ export type RunJSDocMethodDoc =
1652
+ | string
1653
+ | {
1654
+ description?: string;
1655
+ detail?: string;
1656
+ examples?: string[];
1657
+ completion?: RunJSDocCompletionDoc;
1658
+ };
1659
+
1660
+ export type RunJSDocMeta = {
1661
+ label?: string;
1662
+ properties?: Record<string, RunJSDocPropertyDoc>;
1663
+ methods?: Record<string, RunJSDocMethodDoc>;
1664
+ snippets?: Record<string, any>;
1665
+ };
1666
+
1667
+ const __runjsClassDefaultMeta = new WeakMap<Function, RunJSDocMeta>();
1668
+ const __runjsClassLocaleMeta = new WeakMap<Function, Map<string, RunJSDocMeta>>();
1669
+ const __runjsDocCache = new WeakMap<Function, Map<string, RunJSDocMeta>>();
1670
+
1671
+ function __runjsDeepMerge(base: any, patch: any) {
1672
+ if (patch === null) return undefined;
1673
+ if (Array.isArray(base) || Array.isArray(patch) || typeof base !== 'object' || typeof patch !== 'object') {
1674
+ return patch ?? base;
1675
+ }
1676
+ const out: any = { ...base };
1677
+ for (const k of Object.keys(patch)) {
1678
+ const v = __runjsDeepMerge(base?.[k], patch[k]);
1679
+ if (typeof v === 'undefined') delete out[k];
1680
+ else out[k] = v;
1681
+ }
1682
+ return out;
1683
+ }
1684
+ export class FlowRunJSContext extends FlowContext {
1685
+ constructor(delegate: FlowContext) {
1686
+ super();
1687
+ this.addDelegate(delegate);
1688
+ this.defineProperty('React', { value: React });
1689
+ this.defineProperty('antd', { value: antd });
1690
+ // 为 JS 运行时代码提供带有 antd/App/ConfigProvider 包裹的 React 根
1691
+ // 保持与 ReactDOMClient 接口一致,优先覆盖 createRoot,其余方法透传
1692
+ const ReactDOMShim: any = {
1693
+ ...ReactDOMClient,
1694
+ createRoot: (container: Element | DocumentFragment, options?: any) => {
1695
+ // 兼容 ElementProxy:若传入的是代理对象,取其底层原生元素
1696
+ const realContainer: any = (container as any)?.__el || container;
1697
+ // 使用引擎自带的 reactView.createRoot,以继承应用内的 ConfigProvider/App 上下文与主题
1698
+ return this.engine.reactView.createRoot(realContainer as HTMLElement, options);
1699
+ },
1700
+ };
1701
+ this.defineProperty('ReactDOM', { value: ReactDOMShim });
1702
+
1703
+ // Convenience: ctx.render(<App />[, container])
1704
+ // - container defaults to ctx.element if available
1705
+ // - internally uses engine.reactView.createRoot to inherit app context
1706
+ // - caches root per container via global WeakMap
1707
+ this.defineMethod(
1708
+ 'render',
1709
+ function (
1710
+ this: any,
1711
+ vnode: React.ReactElement | Node | DocumentFragment | string,
1712
+ container?: Element | DocumentFragment,
1713
+ ) {
1714
+ const el = (container as any) || (this.element as any);
1715
+ if (!el) throw new Error('ctx.render: container not provided and ctx.element is not available');
1716
+ const containerEl: any = (el as any)?.__el || el; // unwrap ElementProxy
1717
+ const globalRef: any = globalThis as any;
1718
+ globalRef.__nbRunjsRoots = globalRef.__nbRunjsRoots || new WeakMap<any, any>();
1719
+ const rootMap: WeakMap<any, any> = globalRef.__nbRunjsRoots;
1720
+
1721
+ // If vnode is string (HTML), unmount react root and set sanitized HTML
1722
+ if (typeof vnode === 'string') {
1723
+ const existingRoot = rootMap.get(containerEl);
1724
+ if (existingRoot && typeof existingRoot.unmount === 'function') {
1725
+ try {
1726
+ existingRoot.unmount();
1727
+ } finally {
1728
+ rootMap.delete(containerEl);
1729
+ }
1730
+ }
1731
+ const proxy: any = new ElementProxy(containerEl);
1732
+ proxy.innerHTML = String(vnode ?? '');
1733
+ return null;
1734
+ }
1735
+
1736
+ // If vnode is a DOM Node or DocumentFragment, unmount and replace content
1737
+ if (
1738
+ vnode &&
1739
+ (vnode as any).nodeType &&
1740
+ ((vnode as any).nodeType === 1 || (vnode as any).nodeType === 3 || (vnode as any).nodeType === 11)
1741
+ ) {
1742
+ const existingRoot = rootMap.get(containerEl);
1743
+ if (existingRoot && typeof existingRoot.unmount === 'function') {
1744
+ try {
1745
+ existingRoot.unmount();
1746
+ } finally {
1747
+ rootMap.delete(containerEl);
1748
+ }
1749
+ }
1750
+ while (containerEl.firstChild) containerEl.removeChild(containerEl.firstChild);
1751
+ containerEl.appendChild(vnode as any);
1752
+ return null;
1753
+ }
1754
+
1755
+ let root = rootMap.get(containerEl);
1756
+ if (!root) {
1757
+ root = this.ReactDOM.createRoot(containerEl);
1758
+ rootMap.set(containerEl, root);
1759
+ }
1760
+ root.render(vnode as any);
1761
+ return root;
1762
+ },
1763
+ );
1764
+ }
1765
+ static define(meta: RunJSDocMeta, options?: { locale?: string }) {
1766
+ const locale = options?.locale;
1767
+ if (locale) {
1768
+ const map = __runjsClassLocaleMeta.get(this) || new Map<string, RunJSDocMeta>();
1769
+ const prev = map.get(locale) || {};
1770
+ map.set(locale, __runjsDeepMerge(prev, meta));
1771
+ __runjsClassLocaleMeta.set(this, map);
1772
+ } else {
1773
+ const prev = __runjsClassDefaultMeta.get(this) || {};
1774
+ __runjsClassDefaultMeta.set(this, __runjsDeepMerge(prev, meta));
1775
+ }
1776
+ __runjsDocCache.delete(this);
1777
+ }
1778
+ static getDoc(locale?: string): RunJSDocMeta {
1779
+ const self = this as any as Function;
1780
+ let cacheForClass = __runjsDocCache.get(self);
1781
+ const cacheKey = String(locale || 'default');
1782
+ if (cacheForClass && cacheForClass.has(cacheKey)) return cacheForClass.get(cacheKey)!;
1783
+ const chain: Function[] = [];
1784
+ let cur: any = self;
1785
+ while (cur && cur.prototype) {
1786
+ chain.unshift(cur);
1787
+ cur = Object.getPrototypeOf(cur);
1788
+ }
1789
+ let merged: RunJSDocMeta = {};
1790
+ for (const cls of chain) {
1791
+ merged = __runjsDeepMerge(merged, __runjsClassDefaultMeta.get(cls) || {});
1792
+ }
1793
+ if (locale) {
1794
+ for (const cls of chain) {
1795
+ const lmap = __runjsClassLocaleMeta.get(cls);
1796
+ if (lmap && lmap.has(locale)) {
1797
+ merged = __runjsDeepMerge(merged, lmap.get(locale));
1798
+ }
1799
+ }
1800
+ }
1801
+ if (!cacheForClass) {
1802
+ cacheForClass = new Map<string, RunJSDocMeta>();
1803
+ __runjsDocCache.set(self, cacheForClass);
1804
+ }
1805
+ cacheForClass.set(cacheKey, merged);
1806
+ return merged;
1807
+ }
1808
+ }
package/src/flowEngine.ts CHANGED
@@ -130,7 +130,7 @@ export class FlowEngine {
130
130
  */
131
131
  public reactView: ReactView;
132
132
  /**
133
- * Flow executor that runs flows and auto-flows.
133
+ * Flow executor that runs event flows.
134
134
  */
135
135
  public executor: FlowExecutor;
136
136
 
@@ -734,6 +734,17 @@ export class FlowEngine {
734
734
  return this.removeModel(uid);
735
735
  }
736
736
 
737
+ /**
738
+ * Duplicate a model tree via repository API.
739
+ * Returns the duplicated model JSON (root with subModels) or null if not available.
740
+ * @param {string} uid UID of the model to duplicate
741
+ * @returns {Promise<any | null>} Duplicated model JSON or null
742
+ */
743
+ async duplicateModel(uid: string) {
744
+ if (!this.ensureModelRepository()) return null;
745
+ return this._modelRepository.duplicate(uid);
746
+ }
747
+
737
748
  /**
738
749
  * Replace a model instance with a new instance of a class.
739
750
  * @template T New model type
@@ -803,7 +814,7 @@ export class FlowEngine {
803
814
  // 7. 触发事件以通知其他部分模型已替换
804
815
  if (currentParent) {
805
816
  currentParent.emitter.setPaused(false);
806
- currentParent.parent.invalidateAutoFlowCache(true);
817
+ currentParent.parent.invalidateFlowCache('beforeRender', true);
807
818
  currentParent.parent?.rerender();
808
819
  currentParent.emitter.emit('onSubModelReplaced', { oldModel, newModel });
809
820
  }
@@ -837,7 +848,8 @@ export class FlowEngine {
837
848
  return false;
838
849
  }
839
850
 
840
- const findIndex = (model: FlowModel) => subModels.findIndex((item) => item.uid === model.uid);
851
+ const subModelsCopy = [...subModels];
852
+ const findIndex = (model: FlowModel) => subModelsCopy.findIndex((item) => item.uid === model.uid);
841
853
 
842
854
  const currentIndex = findIndex(sourceModel);
843
855
  const targetIndex = findIndex(targetModel);
@@ -853,14 +865,17 @@ export class FlowEngine {
853
865
  }
854
866
 
855
867
  // 使用splice直接移动数组元素(O(n)比排序O(n log n)更快)
856
- const [movedModel] = subModels.splice(currentIndex, 1);
857
- subModels.splice(targetIndex, 0, movedModel);
868
+ const [movedModel] = subModelsCopy.splice(currentIndex, 1);
869
+ subModelsCopy.splice(targetIndex, 0, movedModel);
858
870
 
859
871
  // 重新分配连续的sortIndex
860
- subModels.forEach((model, index) => {
872
+ subModelsCopy.forEach((model, index) => {
861
873
  model.sortIndex = index;
862
874
  });
863
875
 
876
+ // 更新父模型的subModels引用
877
+ sourceModel.parent.subModels[sourceModel.subKey] = subModelsCopy;
878
+
864
879
  return true;
865
880
  };
866
881
  move(sourceModel, targetModel);
@@ -29,6 +29,7 @@ import {
29
29
  resolveStepUiSchema,
30
30
  resolveUiMode,
31
31
  setupRuntimeContextSteps,
32
+ buildSettingsViewInputArgs,
32
33
  } from './utils';
33
34
  import { FlowStepContext } from './hooks/useFlowStep';
34
35
 
@@ -205,8 +206,7 @@ export class FlowSettings {
205
206
  Upload,
206
207
  } = await import('@formily/antd-v5');
207
208
 
208
- // 单独导入 Button 组件
209
- const { Button } = await import('antd');
209
+ const { Button, Alert } = await import('antd');
210
210
 
211
211
  // 注册基础组件
212
212
  this.components.Form = Form;
@@ -254,6 +254,7 @@ export class FlowSettings {
254
254
  this.components.Space = Space;
255
255
  this.components.Editable = Editable;
256
256
  this.components.PreviewText = PreviewText;
257
+ this.components.Alert = Alert;
257
258
 
258
259
  // 注册按钮组件
259
260
  this.components.Button = Button;
@@ -464,12 +465,14 @@ export class FlowSettings {
464
465
  flowEngine,
465
466
  form,
466
467
  onFormValuesChange,
468
+ key,
467
469
  }: {
468
470
  uiSchema: any;
469
471
  initialValues: any;
470
472
  flowEngine: any;
471
473
  form?: any;
472
474
  onFormValuesChange?: (form: any) => void;
475
+ key?: string;
473
476
  }): React.ReactElement {
474
477
  // 获取 scopes 和 components
475
478
  const scopes = {
@@ -496,7 +499,7 @@ export class FlowSettings {
496
499
 
497
500
  return React.createElement(
498
501
  FormProviderWithForm,
499
- { form, initialValues, onFormValuesChange },
502
+ { form, initialValues, onFormValuesChange, key },
500
503
  React.createElement(SchemaField as any, {
501
504
  schema: compiledSchema,
502
505
  components: flowEngine?.flowSettings?.components || {},
@@ -601,7 +604,7 @@ export class FlowSettings {
601
604
  let actionDefaultParams: Record<string, any> = {};
602
605
  let uiMode;
603
606
  if (step.use) {
604
- const action = (model as any).flowEngine?.getAction?.(step.use);
607
+ const action = model.getAction?.(step.use);
605
608
  if (action) {
606
609
  actionDefaultParams = action.defaultParams || {};
607
610
  stepTitle = stepTitle || action.title;
@@ -764,6 +767,8 @@ export class FlowSettings {
764
767
  zIndex: 5000,
765
768
  // 允许透传其它 props(如 maskClosable、footer 等),但确保 content 由我们接管
766
769
  ...modeProps,
770
+ // 统一构造 settings 弹窗的 inputArgs(集合/记录/父导航/关联)
771
+ inputArgs: buildSettingsViewInputArgs(model as any, (modeProps as any)?.inputArgs),
767
772
  content: (currentView, viewCtx) => {
768
773
  viewCtx?.defineMethod('getStepFormValues', (flowKey: string, stepKey: string) => {
769
774
  return forms.get(keyOf({ flowKey, stepKey }))?.values;
@@ -35,7 +35,9 @@ export function useApplyAutoFlows(
35
35
 
36
36
  const { loading, error } = useRequest(
37
37
  async () => {
38
- await model.applyAutoFlows(inputArgs);
38
+ if (!model) return;
39
+ // beforeRender 在模型层默认顺序执行并默认使用缓存(可覆盖)
40
+ await model.dispatchEvent('beforeRender', inputArgs);
39
41
  },
40
42
  {
41
43
  refreshDeps: [model, inputArgs],
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export * from './types';
12
12
 
13
13
  // 工具函数
14
14
  export * from './utils';
15
+ export { compileRunJs } from './utils/jsxTransform';
15
16
 
16
17
  // 资源类
17
18
  export * from './resources';
@@ -31,8 +32,18 @@ export * from './ElementProxy';
31
32
  export * from './flowContext';
32
33
  export * from './FlowContextProvider';
33
34
  export * from './JSRunner';
34
- export * from './runjs-context';
35
+ export {
36
+ getRunJSDocFor,
37
+ createJSRunnerWithVersion,
38
+ getRunJSScenesForModel,
39
+ getRunJSScenesForContext,
40
+ } from './runjs-context/helpers';
41
+ export { RunJSContextRegistry, getModelClassName } from './runjs-context/registry';
42
+ export { setupRunJSContexts } from './runjs-context/setup';
43
+ export { getSnippetBody, listSnippetsForContext } from './runjs-context/snippets';
35
44
 
36
45
  export * from './views';
37
46
 
38
47
  export * from './FlowDefinition';
48
+ export { createViewScopedEngine } from './ViewScopedFlowEngine';
49
+ export { createBlockScopedEngine } from './BlockScopedFlowEngine';