@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
@@ -0,0 +1,45 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSColumnRunJSContext],
15
+ prefix: 'sn-col-open-dialog',
16
+ label: 'Cell dialog with row data',
17
+ description: 'Render a button in cell to open dialog via ctx.openView with current row context',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '单元格对话框(显示行数据)',
21
+ description: '在单元格渲染按钮,点击后通过 ctx.openView 打开弹窗并传入当前行上下文',
22
+ },
23
+ },
24
+ content: `
25
+ // Render a button inside the cell
26
+ ctx.element.innerHTML = '<button class="nb-cell-btn" style="padding:4px 8px">' + ctx.t('View') + '</button>';
27
+
28
+ const button = ctx.element.querySelector('.nb-cell-btn');
29
+ const popupUid = ctx.model.uid + '-1'; // popupUid should be stable and better bound to ctx.model.uid
30
+ const primaryKey = ctx.collection?.primaryKey || 'id';
31
+
32
+ button?.addEventListener('click', async () => {
33
+ await ctx.openView(popupUid, {
34
+ mode: 'dialog',
35
+ title: ctx.t('Row detail'),
36
+ params: {
37
+ filterByTk: ctx.record?.[primaryKey],
38
+ record: ctx.record,
39
+ },
40
+ });
41
+ });
42
+ `,
43
+ };
44
+
45
+ export default snippet;
@@ -7,10 +7,20 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- export default {
11
- contexts: ['JSCollectionActionRunJSContext'],
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
12
15
  prefix: 'sn-act-selected-count',
13
16
  label: 'Selected count',
17
+ description: 'Show number of selected rows in list action',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '选中数量',
21
+ description: '提示当前选中行的数量',
22
+ },
23
+ },
14
24
  content: `
15
25
  const rows = ctx.resource?.getSelectedRows?.() || [];
16
26
  if (!rows.length) {
@@ -20,3 +30,5 @@ if (!rows.length) {
20
30
  }
21
31
  `,
22
32
  };
33
+
34
+ export default snippet;
@@ -0,0 +1,60 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSColumnRunJSContext],
15
+ prefix: 'sn-col-concat',
16
+ label: 'Concat two fields',
17
+ description: 'Combine two field values into the current column cell',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '拼接两个字段值',
21
+ description: '在自定义列中拼接两个字段的值作为显示内容',
22
+ },
23
+ },
24
+ content: `
25
+ // Demo helper: infer previous columns' dataIndex values based on the current column position
26
+ // In production, hardcode field names to avoid surprises when columns are reordered
27
+ function resolvePreviousDataIndexes() {
28
+ const parent = ctx.model?.parent;
29
+ const list = parent?.subModels?.columns;
30
+ if (!Array.isArray(list)) return [];
31
+ const currentUid = ctx.model?.uid;
32
+ const currentIndex = list.findIndex((item) => item?.uid === currentUid);
33
+ if (currentIndex <= 0) return [];
34
+ return list
35
+ .slice(Math.max(0, currentIndex - 2), currentIndex)
36
+ .map((item) => (item && item.props ? item.props.dataIndex : undefined))
37
+ .filter((key) => typeof key === 'string' && key.length > 0);
38
+ }
39
+
40
+ const [autoFieldA, autoFieldB] = resolvePreviousDataIndexes();
41
+
42
+ // Fallback: manually specify field keys when auto detection is not enough
43
+ const fieldA = autoFieldA || 'firstName';
44
+ const fieldB = autoFieldB || 'lastName';
45
+
46
+ const normalize = (value) => {
47
+ if (value === undefined || value === null) return '';
48
+ return String(value).trim();
49
+ };
50
+
51
+ const valueA = normalize(ctx.record?.[fieldA]);
52
+ const valueB = normalize(ctx.record?.[fieldB]);
53
+
54
+ const parts = [valueA, valueB].filter((item) => item.length > 0);
55
+
56
+ ctx.element.textContent = parts.length ? parts.join(' / ') : ctx.t('N/A');
57
+ `,
58
+ };
59
+
60
+ export default snippet;
@@ -0,0 +1,36 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
15
+ prefix: 'sn-act-destroy-selected',
16
+ label: 'Destroy selected rows',
17
+ description: 'Delete selected rows via resource.destroySelectedRows()',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '删除选中行',
21
+ description: '通过 resource.destroySelectedRows() 删除选中行',
22
+ },
23
+ },
24
+ content: `
25
+ const rows = ctx.resource?.getSelectedRows?.() || [];
26
+ if (!rows.length) {
27
+ ctx.message.warning(ctx.t('Please select data'));
28
+ return;
29
+ }
30
+
31
+ await ctx.resource.destroySelectedRows();
32
+ ctx.message.success(ctx.t('Deleted {{count}} rows', { count: rows.length }));
33
+ `,
34
+ };
35
+
36
+ export default snippet;
@@ -0,0 +1,45 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
15
+ prefix: 'sn-act-export',
16
+ label: 'Export selected rows as JSON',
17
+ description: 'Download selected rows as a JSON file',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '导出选中行为 JSON',
21
+ description: '将选中的行导出为 JSON 文件下载',
22
+ },
23
+ },
24
+ content: `
25
+ const rows = ctx.resource?.getSelectedRows?.() || [];
26
+ if (!rows.length) {
27
+ ctx.message.warning(ctx.t('Please select at least one row'));
28
+ return;
29
+ }
30
+
31
+ // Create JSON file and download
32
+ const jsonStr = JSON.stringify(rows, null, 2);
33
+ const blob = new Blob([jsonStr], { type: 'application/json' });
34
+ const url = URL.createObjectURL(blob);
35
+ const link = document.createElement('a');
36
+ link.href = url;
37
+ link.download = \`export-\${new Date().toISOString().split('T')[0]}.json\`;
38
+ link.click();
39
+ URL.revokeObjectURL(url);
40
+
41
+ ctx.message.success(ctx.t('Exported {{count}} records', { count: rows.length }));
42
+ `,
43
+ };
44
+
45
+ export default snippet;
@@ -7,10 +7,20 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- export default {
11
- contexts: ['JSCollectionActionRunJSContext'],
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
12
15
  prefix: 'sn-act-iterate',
13
16
  label: 'Iterate selected rows',
17
+ description: 'Loop through selected rows and process each record',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '遍历选中行',
21
+ description: '遍历选中行并处理每条记录',
22
+ },
23
+ },
14
24
  content: `
15
25
  const rows = ctx.resource?.getSelectedRows?.() || [];
16
26
  for (const row of rows) {
@@ -19,3 +29,5 @@ for (const row of rows) {
19
29
  ctx.message.success(ctx.t('Processed {{count}} rows', { count: rows.length }));
20
30
  `,
21
31
  };
32
+
33
+ export default snippet;
@@ -7,11 +7,15 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ export type SnippetContextSpecifier = string | { name: string } | (new (...args: any[]) => any);
11
+
10
12
  export type SnippetModule = {
11
13
  content: string;
12
- contexts?: string[]; // e.g., ['JSBlockRunJSContext'] or ['*']
14
+ contexts?: SnippetContextSpecifier[]; // e.g., [JSBlockRunJSContext] or ['*']
13
15
  versions?: string[]; // e.g., ['v1'] or ['*']
16
+ scenes?: string[]; // logical placement hints like ['form', 'table']
14
17
  prefix?: string; // completion trigger text
15
18
  label?: string; // display name in snippets list
16
19
  description?: string; // optional longer description
20
+ locales?: Record<string, { label?: string; description?: string }>;
17
21
  };
package/src/types.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  import { ISchema } from '@formily/json-schema';
11
11
  import { SubModelItem } from './components';
12
12
  import { FlowContext, FlowModelContext, FlowRuntimeContext, FlowSettingsContext } from './flowContext';
13
+ import type { PropertyOptions } from './flowContext';
13
14
  import type { FlowEngine } from './flowEngine';
14
15
  import type { FlowModel } from './models';
15
16
  import { FilterGroupOptions } from './resources';
@@ -134,6 +135,8 @@ export enum ActionScene {
134
135
  BLOCK_LINKAGE_RULES = 1,
135
136
  /** 表单字段级联动规则可用 */
136
137
  FIELD_LINKAGE_RULES,
138
+ /** 子表单字段级联动规则可用 */
139
+ SUB_FORM_FIELD_LINKAGE_RULES,
137
140
  /** 详情字段级联动规则可用 */
138
141
  DETAILS_FIELD_LINKAGE_RULES,
139
142
  /** 按钮级联动规则可用 */
@@ -157,6 +160,26 @@ export interface ActionDefinition<TModel extends FlowModel = FlowModel, TCtx ext
157
160
  uiMode?: StepUIMode | ((ctx: FlowRuntimeContext<TModel>) => StepUIMode | Promise<StepUIMode>);
158
161
  scene?: ActionScene | ActionScene[];
159
162
  sort?: number;
163
+ /**
164
+ * 在执行 Action 前为 ctx 定义临时属性。
165
+ * - 仅支持 PropertyOptions 形态(例如:{ foo: { value: 5 } });
166
+ * - 或函数形式(接收 ctx,返回 PropertyOptions 对象;支持 Promise)。
167
+ */
168
+ defineProperties?:
169
+ | Record<string, PropertyOptions>
170
+ | ((ctx: TCtx) => Record<string, PropertyOptions> | Promise<Record<string, PropertyOptions>>);
171
+ /**
172
+ * 在执行 Action 前为 ctx 定义临时方法。
173
+ * - 支持 JSON 形式(对象的值应为函数)
174
+ * - 或函数形式(接收 ctx,返回方法对象;支持 Promise)
175
+ */
176
+ defineMethods?:
177
+ | Record<string, (this: TCtx, ...args: any[]) => any>
178
+ | ((
179
+ ctx: TCtx,
180
+ ) =>
181
+ | Record<string, (this: TCtx, ...args: any[]) => any>
182
+ | Promise<Record<string, (this: TCtx, ...args: any[]) => any>>);
160
183
  }
161
184
 
162
185
  /**
@@ -185,6 +208,16 @@ export type FlowEvent<TModel extends FlowModel = FlowModel> =
185
208
  | FlowEventName
186
209
  | { eventName: FlowEventName; defaultParams?: Record<string, any> };
187
210
 
211
+ /**
212
+ * 事件分发选项。
213
+ */
214
+ export interface DispatchEventOptions {
215
+ /** 是否顺序执行(默认并行) */
216
+ sequential?: boolean;
217
+ /** 是否使用缓存(默认 false;beforeRender 的默认值为 true,可覆盖) */
218
+ useCache?: boolean;
219
+ }
220
+
188
221
  /**
189
222
  * 事件定义:用于事件注册表(全局/模型类级)。
190
223
  */
@@ -300,6 +333,7 @@ export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
300
333
  save(model: T, options?: { onlyStepParams?: boolean }): Promise<Record<string, any>>;
301
334
  destroy(uid: string): Promise<boolean>;
302
335
  move(sourceId: string, targetId: string, position: 'before' | 'after'): Promise<void>;
336
+ duplicate(uid: string): Promise<Record<string, any> | null>;
303
337
  }
304
338
 
305
339
  /**
@@ -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
+ });
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { describe, expect, it } from 'vitest';
11
- import { createSafeDocument, createSafeWindow } from '../safeGlobals';
11
+ import { createSafeDocument, createSafeWindow, createSafeNavigator } from '../safeGlobals';
12
12
 
13
13
  describe('safeGlobals', () => {
14
14
  it('createSafeWindow exposes only allowed globals and extras', () => {
@@ -26,4 +26,25 @@ describe('safeGlobals', () => {
26
26
  expect(doc.bar).toBe(true);
27
27
  expect(() => doc.cookie).toThrow(/not allowed/);
28
28
  });
29
+
30
+ it('createSafeNavigator exposes limited props and guards others', () => {
31
+ const nav: any = createSafeNavigator();
32
+ // clipboard object should always exist
33
+ expect(typeof nav.clipboard).toBe('object');
34
+ // writeText may or may not exist depending on environment
35
+ if (typeof navigator !== 'undefined' && (navigator as any).clipboard?.writeText) {
36
+ expect(typeof nav.clipboard.writeText).toBe('function');
37
+ } else {
38
+ expect(typeof nav.clipboard.writeText === 'undefined' || typeof nav.clipboard.writeText === 'function').toBe(
39
+ true,
40
+ );
41
+ }
42
+ // readable properties
43
+ expect(() => void nav.onLine).not.toThrow();
44
+ expect(() => void nav.language).not.toThrow();
45
+ expect(() => void nav.languages).not.toThrow();
46
+ // blocked properties
47
+ expect(() => (nav as any).geolocation).toThrow(/not allowed/);
48
+ expect(() => (nav as any).userAgent).toThrow(/not allowed/);
49
+ });
29
50
  });
@@ -0,0 +1,72 @@
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 type { FlowModel } from '../models';
11
+ import { inferRecordRef } from './variablesParams';
12
+
13
+ /**
14
+ * 统一构造设置弹窗 openView 的 inputArgs:
15
+ * - collectionName/dataSourceKey/filterByTk:优先从 model.context 推断;否则回退父视图 inputArgs
16
+ * - sourceId:优先从 resource.getSourceId();否则回退父视图 inputArgs
17
+ * - associationName:来自 association.resourceName 或 resource.getResourceName()
18
+ * - navigation:父视图 navigation 或传入的 navigationOverride
19
+ */
20
+ export function buildSettingsViewInputArgs(
21
+ model: FlowModel,
22
+ extra?: Record<string, any>,
23
+ options?: { navigationOverride?: any },
24
+ ): Record<string, any> {
25
+ const defaults: Record<string, any> = {};
26
+
27
+ try {
28
+ // 1) 当前记录/集合
29
+ const ref = inferRecordRef((model as any).context);
30
+ if (ref?.collection) {
31
+ defaults.collectionName = ref.collection;
32
+ defaults.dataSourceKey = ref.dataSourceKey || 'main';
33
+ defaults.filterByTk = ref.filterByTk;
34
+ }
35
+
36
+ // 2) 回退父视图 inputArgs(如在抽屉/页面中)
37
+ const parentArgs = (model as any)?.context?.view?.inputArgs || {};
38
+ if (!defaults.collectionName && parentArgs?.collectionName) {
39
+ defaults.collectionName = parentArgs.collectionName;
40
+ defaults.dataSourceKey = parentArgs.dataSourceKey || defaults.dataSourceKey || 'main';
41
+ }
42
+ if (defaults.filterByTk == null && parentArgs?.filterByTk != null) {
43
+ defaults.filterByTk = parentArgs.filterByTk;
44
+ }
45
+ if (defaults.sourceId == null && parentArgs?.sourceId != null) {
46
+ defaults.sourceId = parentArgs.sourceId;
47
+ }
48
+
49
+ // 3) 导航(用于推断“上级弹窗”)
50
+ const nav = options?.navigationOverride ?? (model as any)?.context?.view?.navigation;
51
+ if (nav) {
52
+ defaults.navigation = nav;
53
+ }
54
+
55
+ // 4) 直接从资源读取 sourceId(优先级高于父视图)
56
+ const sid = (model as any)?.context?.resource?.getSourceId?.();
57
+ if (sid !== undefined && sid !== null && String(sid) !== '') {
58
+ defaults.sourceId = sid;
59
+ }
60
+
61
+ // 5) 关联名(用于“上级记录”)
62
+ const assocName =
63
+ (model as any)?.context?.association?.resourceName || (model as any)?.context?.resource?.getResourceName?.();
64
+ if (typeof assocName === 'string' && assocName) {
65
+ defaults.associationName = assocName;
66
+ }
67
+ } catch (_) {
68
+ // 忽略推断异常
69
+ }
70
+
71
+ return { ...defaults, ...(extra || {}) };
72
+ }
@@ -0,0 +1,142 @@
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 { FlowContext } from '../flowContext';
11
+ import type { ActionDefinition } from '../types';
12
+ import type { PropertyOptions } from '../flowContext';
13
+
14
+ // 临时上下文:
15
+ // - 读:优先从 scoped(临时定义)读取,兜底 parent;
16
+ // - 写:统一写入 parent(不污染 scoped);
17
+ // - 注入:create 阶段 define* 写入 scoped;运行阶段 define* 写入 parent。
18
+ type ContextDefsLike<TCtx extends FlowContext> =
19
+ | Partial<Pick<ActionDefinition<any, TCtx>, 'defineProperties' | 'defineMethods'>>
20
+ | null
21
+ | undefined;
22
+
23
+ export async function createEphemeralContext<TCtx extends FlowContext>(
24
+ parent: TCtx,
25
+ contextDefs?: ContextDefsLike<TCtx>,
26
+ ): Promise<TCtx> {
27
+ // 若未提供任何上下文定义,直接复用父级上下文,避免不必要的代理包装
28
+ if (contextDefs == null || (!contextDefs.defineProperties && !contextDefs.defineMethods)) {
29
+ return parent;
30
+ }
31
+ // 1) 创建一个新的 FlowContext,专门承载“临时定义”(defineProperty/defineMethod)
32
+ const scoped = new FlowContext();
33
+ // 2) 读取优先:先从 scoped 自身取(_props/_methods),否则委托到 parent(仅 _props/_methods)
34
+ scoped.addDelegate(parent);
35
+
36
+ // 3) 先创建 scoped 的代理,用于注入阶段(define* 直达 scoped;读写行为与最终代理一致)
37
+ const scopedProxy = scoped.createProxy();
38
+ const scopedObj = scopedProxy as unknown as object;
39
+ const parentObj = parent as unknown as object;
40
+ const getFromParent = (key: PropertyKey) => {
41
+ const val = Reflect.get(parentObj, key, parentObj);
42
+ return typeof val === 'function' ? (val as Function).bind(parent) : val;
43
+ };
44
+ const hasInScopedOrParent = (key: PropertyKey) =>
45
+ key === 'defineProperty' || key === 'defineMethod' || Reflect.has(scopedObj, key) || Reflect.has(parentObj, key);
46
+ const injectionProxy = new Proxy(scopedProxy as TCtx, {
47
+ get(_t, key: PropertyKey, receiver) {
48
+ if (typeof key === 'string') {
49
+ // 注入阶段:允许在 defLike 的函数体中调用 ctx.defineProperty/defineMethod 写入 scoped
50
+ if (key === 'defineProperty') {
51
+ return (propKey: string, options: any) => (scoped as FlowContext).defineProperty(propKey, options);
52
+ }
53
+ if (key === 'defineMethod') {
54
+ return (name: string, fn: any, des?: string) => (scoped as FlowContext).defineMethod(name, fn, des);
55
+ }
56
+ if (Reflect.has(scopedObj, key)) {
57
+ return Reflect.get(scopedObj, key, receiver);
58
+ }
59
+ return getFromParent(key);
60
+ }
61
+ return Reflect.get(scopedObj, key, receiver);
62
+ },
63
+ set(_t, key: PropertyKey, value: unknown) {
64
+ return Reflect.set(parentObj, key, value);
65
+ },
66
+ has(_t, key: PropertyKey) {
67
+ return hasInScopedOrParent(key);
68
+ },
69
+ getOwnPropertyDescriptor(_t, key: PropertyKey) {
70
+ return Object.getOwnPropertyDescriptor(scopedObj, key) || Object.getOwnPropertyDescriptor(parentObj, key);
71
+ },
72
+ });
73
+
74
+ // 如果提供了 contextDefs,则在创建时即注入定义,便于外部更简洁地使用
75
+ if (contextDefs) {
76
+ const defs = Array.isArray(contextDefs) ? contextDefs : [contextDefs];
77
+ for (const defLike of defs) {
78
+ if (!defLike) continue;
79
+ // 1) defineProperties -> 写入到 scoped(避免污染父级)
80
+ const dp = (defLike as any).defineProperties;
81
+ if (dp) {
82
+ const raw = typeof dp === 'function' ? await dp(injectionProxy as TCtx) : dp;
83
+ if (!raw || typeof raw !== 'object') {
84
+ throw new TypeError('defineProperties must return an object of PropertyOptions');
85
+ }
86
+ const propsDef = raw as Record<string, PropertyOptions>;
87
+ for (const [key, options] of Object.entries(propsDef)) {
88
+ if (!options || typeof options !== 'object') {
89
+ throw new TypeError(`defineProperties['${key}'] must be a PropertyOptions object`);
90
+ }
91
+ // 直接在 scoped 上定义,确保仅限本次临时作用域
92
+ (scoped as FlowContext).defineProperty(key, options);
93
+ }
94
+ }
95
+ // 2) defineMethods -> 写入到 scoped(避免污染父级)
96
+ const dm = (defLike as any).defineMethods;
97
+ if (dm) {
98
+ const raw = typeof dm === 'function' ? await dm(injectionProxy as TCtx) : dm;
99
+ if (!raw || typeof raw !== 'object') {
100
+ throw new TypeError('defineMethods must return an object of functions');
101
+ }
102
+ const methodsDef = raw as Record<string, (this: TCtx, ...args: any[]) => any>;
103
+ for (const [key, fn] of Object.entries(methodsDef)) {
104
+ if (typeof fn !== 'function') {
105
+ throw new TypeError(`defineMethods['${key}'] must be a function`);
106
+ }
107
+ (scoped as FlowContext).defineMethod(key, fn as any);
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ // 4) 创建最终对外代理:读取优先 scoped,兜底父级,且后续 define* 写入父级
114
+ const outerProxy = new Proxy(scopedProxy as TCtx, {
115
+ get(_t, key: PropertyKey, receiver) {
116
+ if (typeof key === 'string') {
117
+ if (key === 'defineProperty') {
118
+ return (propKey: string, options: any) => (parent as FlowContext).defineProperty(propKey, options);
119
+ }
120
+ if (key === 'defineMethod') {
121
+ return (name: string, fn: any, des?: string) => (parent as FlowContext).defineMethod(name, fn, des);
122
+ }
123
+ if (Reflect.has(scopedObj, key)) {
124
+ return Reflect.get(scopedObj, key, receiver);
125
+ }
126
+ return getFromParent(key);
127
+ }
128
+ return Reflect.get(scopedObj, key, receiver);
129
+ },
130
+ set(_t, key: PropertyKey, value: unknown) {
131
+ return Reflect.set(parentObj, key, value);
132
+ },
133
+ has(_t, key: PropertyKey) {
134
+ return hasInScopedOrParent(key);
135
+ },
136
+ getOwnPropertyDescriptor(_t, key: PropertyKey) {
137
+ return Object.getOwnPropertyDescriptor(scopedObj, key) || Object.getOwnPropertyDescriptor(parentObj, key);
138
+ },
139
+ });
140
+
141
+ return outerProxy as TCtx;
142
+ }
@@ -48,7 +48,6 @@ export {
48
48
  createRecordMetaFactory,
49
49
  extractUsedVariableNames,
50
50
  extractUsedVariablePaths,
51
- inferParentRecordRef,
52
51
  inferRecordRef,
53
52
  type RecordParamsBuilder,
54
53
  } from './variablesParams';
@@ -58,6 +57,7 @@ export { extractPropertyPath, formatPathToVariable, isVariableExpression } from
58
57
 
59
58
  export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
60
59
  export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
60
+ export { buildSettingsViewInputArgs } from './buildSettingsViewInputArgs';
61
61
 
62
62
  // 安全全局对象(window/document)
63
- export { createSafeDocument, createSafeWindow } from './safeGlobals';
63
+ export { createSafeDocument, createSafeWindow, createSafeNavigator } from './safeGlobals';