@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.
- package/lib/BlockScopedFlowEngine.d.ts +23 -0
- package/lib/BlockScopedFlowEngine.js +90 -0
- package/lib/FlowContextProvider.d.ts +2 -2
- package/lib/FlowContextProvider.js +3 -3
- package/lib/FlowDefinition.d.ts +4 -2
- package/lib/JSRunner.js +3 -0
- package/lib/ViewScopedFlowEngine.d.ts +1 -1
- package/lib/components/FieldModelRenderer.js +10 -4
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +7 -2
- package/lib/components/FlowModelRenderer.d.ts +2 -5
- package/lib/components/FlowModelRenderer.js +16 -47
- package/lib/components/FormItem.js +5 -1
- package/lib/{runjs-context/snippets/global/requireAsync.snippet.d.ts → components/dnd/findModelUidPosition.d.ts} +4 -7
- package/lib/{runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js → components/dnd/findModelUidPosition.js} +23 -19
- package/lib/components/dnd/gridDragPlanner.d.ts +130 -0
- package/lib/components/dnd/gridDragPlanner.js +497 -0
- package/lib/components/dnd/index.d.ts +2 -2
- package/lib/components/dnd/index.js +5 -5
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
- package/lib/components/variables/VariableInput.js +16 -2
- package/lib/components/variables/VariableTag.js +43 -2
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/data-source/index.d.ts +12 -4
- package/lib/data-source/index.js +19 -13
- package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
- package/lib/data-source/sortCollectionsByInherits.js +71 -0
- package/lib/executor/FlowExecutor.d.ts +4 -5
- package/lib/executor/FlowExecutor.js +135 -100
- package/lib/flowContext.d.ts +33 -5
- package/lib/flowContext.js +193 -76
- package/lib/flowEngine.d.ts +8 -1
- package/lib/flowEngine.js +18 -6
- package/lib/flowSettings.d.ts +2 -1
- package/lib/flowSettings.js +12 -8
- package/lib/hooks/useApplyAutoFlows.js +2 -1
- package/lib/index.d.ts +7 -1
- package/lib/index.js +32 -3
- package/lib/locale/en-US.json +4 -2
- package/lib/locale/index.d.ts +4 -0
- package/lib/locale/zh-CN.json +4 -2
- package/lib/models/CollectionFieldModel.d.ts +2 -0
- package/lib/models/CollectionFieldModel.js +43 -3
- package/lib/models/flowModel.d.ts +28 -29
- package/lib/models/flowModel.js +114 -92
- package/lib/models/forkFlowModel.d.ts +4 -4
- package/lib/models/forkFlowModel.js +32 -8
- package/lib/provider.d.ts +3 -1
- package/lib/provider.js +7 -5
- package/lib/resources/multiRecordResource.js +2 -0
- package/lib/resources/singleRecordResource.js +1 -0
- package/lib/resources/sqlResource.d.ts +1 -0
- package/lib/resources/sqlResource.js +20 -24
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
- package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
- package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
- package/lib/runjs-context/contexts/base.d.ts +9 -0
- package/lib/runjs-context/contexts/base.js +183 -0
- package/lib/runjs-context/helpers.d.ts +5 -2
- package/lib/runjs-context/helpers.js +36 -27
- package/lib/runjs-context/registry.d.ts +7 -4
- package/lib/runjs-context/registry.js +10 -42
- package/lib/runjs-context/setup.d.ts +9 -0
- package/lib/runjs-context/setup.js +82 -0
- package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
- package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
- package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
- package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/index.d.ts +14 -3
- package/lib/runjs-context/snippets/index.js +161 -40
- package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
- package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
- package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
- package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
- package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
- package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
- package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
- package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
- package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
- package/lib/runjs-context/snippets/types.d.ts +9 -1
- package/lib/types.d.ts +28 -3
- package/lib/types.js +4 -3
- package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
- package/lib/utils/buildSettingsViewInputArgs.js +75 -0
- package/lib/utils/createEphemeralContext.d.ts +13 -0
- package/lib/utils/createEphemeralContext.js +140 -0
- package/lib/utils/index.d.ts +3 -2
- package/lib/utils/index.js +5 -2
- package/lib/utils/jsxTransform.d.ts +15 -0
- package/lib/utils/jsxTransform.js +68 -0
- package/lib/utils/params-resolvers.js +3 -3
- package/lib/utils/safeGlobals.d.ts +5 -3
- package/lib/utils/safeGlobals.js +40 -0
- package/lib/utils/schema-utils.js +2 -2
- package/lib/utils/serverContextParams.d.ts +1 -0
- package/lib/utils/variablesParams.d.ts +9 -5
- package/lib/utils/variablesParams.js +47 -36
- package/lib/views/PageComponent.js +2 -1
- package/lib/views/createViewMeta.d.ts +29 -1
- package/lib/views/createViewMeta.js +338 -72
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +3 -0
- package/lib/views/useDialog.d.ts +8 -8
- package/lib/views/useDialog.js +8 -7
- package/lib/views/useDrawer.d.ts +8 -8
- package/lib/views/useDrawer.js +40 -26
- package/lib/views/usePage.d.ts +8 -8
- package/lib/views/usePage.js +8 -7
- package/package.json +5 -3
- package/src/BlockScopedFlowEngine.ts +86 -0
- package/src/FlowContextProvider.tsx +4 -2
- package/src/JSRunner.ts +3 -0
- package/src/ViewScopedFlowEngine.ts +1 -1
- package/src/__tests__/JSRunner.test.ts +62 -53
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/createViewMeta.popup.test.ts +132 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
- package/src/__tests__/globalFlowRegistry.test.ts +1 -1
- package/src/__tests__/runjsContext.test.ts +216 -35
- package/src/__tests__/runjsContextImplementations.test.ts +217 -0
- package/src/__tests__/runjsContextRuntime.test.ts +269 -0
- package/src/__tests__/runjsEdgeCases.test.ts +281 -0
- package/src/__tests__/runjsLocales.test.ts +36 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +449 -0
- package/src/__tests__/runjsSnippets.test.ts +140 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
- package/src/components/DynamicFlowsEditor.tsx +3 -4
- package/src/components/FieldModelRenderer.tsx +16 -5
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +6 -2
- package/src/components/FlowModelRenderer.tsx +30 -78
- package/src/components/FormItem.tsx +8 -1
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +5 -5
- package/src/components/__tests__/gridDragPlanner.test.ts +494 -0
- package/src/components/dnd/README.md +149 -0
- package/src/components/dnd/findModelUidPosition.ts +26 -0
- package/src/components/dnd/gridDragPlanner.ts +659 -0
- package/src/components/dnd/index.tsx +3 -3
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +424 -0
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
- package/src/components/variables/VariableInput.tsx +22 -2
- package/src/components/variables/VariableTag.tsx +54 -2
- package/src/components/variables/types.ts +2 -0
- package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
- package/src/data-source/index.ts +17 -11
- package/src/data-source/sortCollectionsByInherits.ts +61 -0
- package/src/executor/FlowExecutor.ts +178 -121
- package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
- package/src/executor/__tests__/flowExecutor.test.ts +151 -5
- package/src/flowContext.ts +266 -97
- package/src/flowEngine.ts +21 -6
- package/src/flowSettings.ts +9 -4
- package/src/hooks/useApplyAutoFlows.ts +3 -1
- package/src/index.ts +12 -1
- package/src/locale/en-US.json +4 -2
- package/src/locale/zh-CN.json +4 -2
- package/src/models/CollectionFieldModel.tsx +43 -4
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +4 -4
- package/src/models/__tests__/flowModel.test.ts +234 -111
- package/src/models/__tests__/forkFlowModel.test.ts +22 -7
- package/src/models/flowModel.tsx +149 -125
- package/src/models/forkFlowModel.ts +41 -8
- package/src/provider.tsx +10 -7
- package/src/resources/multiRecordResource.ts +2 -0
- package/src/resources/singleRecordResource.ts +1 -0
- package/src/resources/sqlResource.ts +20 -25
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
- package/src/runjs-context/contexts/base.ts +171 -0
- package/src/runjs-context/helpers.ts +32 -30
- package/src/runjs-context/registry.ts +16 -47
- package/src/runjs-context/setup.ts +51 -0
- package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
- package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
- package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
- package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/index.ts +177 -39
- package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
- package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
- package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
- package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
- package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
- package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
- package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
- package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
- package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
- package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
- package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
- package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
- package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
- package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
- package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
- package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
- package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
- package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
- package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
- package/src/runjs-context/snippets/types.ts +5 -1
- package/src/types.ts +34 -0
- package/src/utils/__tests__/jsxTransform.test.ts +38 -0
- package/src/utils/__tests__/safeGlobals.test.ts +22 -1
- package/src/utils/buildSettingsViewInputArgs.ts +72 -0
- package/src/utils/createEphemeralContext.ts +142 -0
- package/src/utils/index.ts +2 -2
- package/src/utils/jsxTransform.ts +39 -0
- package/src/utils/params-resolvers.ts +2 -2
- package/src/utils/safeGlobals.ts +49 -3
- package/src/utils/schema-utils.ts +1 -1
- package/src/utils/serverContextParams.ts +1 -0
- package/src/utils/variablesParams.ts +50 -38
- package/src/views/PageComponent.tsx +1 -1
- package/src/views/createViewMeta.ts +393 -70
- package/src/views/index.tsx +1 -0
- package/src/views/useDialog.tsx +12 -10
- package/src/views/useDrawer.tsx +60 -36
- package/src/views/usePage.tsx +13 -10
- package/lib/components/dnd/getMousePositionOnElement.d.ts +0 -50
- package/lib/components/dnd/getMousePositionOnElement.js +0 -95
- package/lib/components/dnd/moveBlock.d.ts +0 -33
- package/lib/components/dnd/moveBlock.js +0 -302
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
- package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
- package/lib/runjs-context/index.d.ts +0 -19
- package/lib/runjs-context/index.js +0 -57
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/api-request-post.snippet.js +0 -42
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +0 -44
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
- package/src/components/dnd/getMousePositionOnElement.ts +0 -115
- package/src/components/dnd/moveBlock.ts +0 -379
- package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
- package/src/runjs-context/index.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
- package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
- package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
- /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
|
@@ -11,14 +11,49 @@ import _ from 'lodash';
|
|
|
11
11
|
import { FlowRuntimeContext } from '../flowContext';
|
|
12
12
|
import { FlowEngine } from '../flowEngine';
|
|
13
13
|
import type { FlowModel } from '../models';
|
|
14
|
+
import type { DispatchEventOptions } from '../types';
|
|
14
15
|
import type { ActionDefinition, ApplyFlowCacheEntry, StepDefinition } from '../types';
|
|
15
16
|
import { FlowExitException, resolveDefaultParams } from '../utils';
|
|
16
17
|
import { FlowExitAllException } from '../utils/exceptions';
|
|
17
18
|
import { setupRuntimeContextSteps } from '../utils/setupRuntimeContextSteps';
|
|
19
|
+
import { createEphemeralContext } from '../utils/createEphemeralContext';
|
|
18
20
|
|
|
19
21
|
export class FlowExecutor {
|
|
20
22
|
constructor(private readonly engine: FlowEngine) {}
|
|
21
23
|
|
|
24
|
+
/** Cache wrapper for applyFlow cache lifecycle */
|
|
25
|
+
private async withApplyFlowCache<T>(cacheKey: string | null, executor: () => Promise<T>): Promise<T> {
|
|
26
|
+
if (!cacheKey || !this.engine) return await executor();
|
|
27
|
+
|
|
28
|
+
const cachedEntry = this.engine.applyFlowCache.get(cacheKey);
|
|
29
|
+
if (cachedEntry) {
|
|
30
|
+
if (cachedEntry.status === 'resolved') return cachedEntry.data as T;
|
|
31
|
+
if (cachedEntry.status === 'rejected') throw cachedEntry.error;
|
|
32
|
+
if (cachedEntry.status === 'pending') return await cachedEntry.promise;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const promise = executor()
|
|
36
|
+
.then((result) => {
|
|
37
|
+
this.engine.applyFlowCache.set(cacheKey, {
|
|
38
|
+
status: 'resolved',
|
|
39
|
+
data: result,
|
|
40
|
+
promise: Promise.resolve(result),
|
|
41
|
+
} as ApplyFlowCacheEntry);
|
|
42
|
+
return result;
|
|
43
|
+
})
|
|
44
|
+
.catch((err) => {
|
|
45
|
+
this.engine.applyFlowCache.set(cacheKey, {
|
|
46
|
+
status: 'rejected',
|
|
47
|
+
error: err,
|
|
48
|
+
promise: Promise.reject(err),
|
|
49
|
+
} as ApplyFlowCacheEntry);
|
|
50
|
+
throw err;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
this.engine.applyFlowCache.set(cacheKey, { status: 'pending', promise } as ApplyFlowCacheEntry);
|
|
54
|
+
return await promise;
|
|
55
|
+
}
|
|
56
|
+
|
|
22
57
|
/**
|
|
23
58
|
* Execute a single flow on model.
|
|
24
59
|
*/
|
|
@@ -46,43 +81,55 @@ export class FlowExecutor {
|
|
|
46
81
|
|
|
47
82
|
let lastResult: any;
|
|
48
83
|
const stepResults: Record<string, any> = flowContext.stepResults;
|
|
84
|
+
|
|
85
|
+
// Build steps with optional eventStep injection (when flow.on is configured)
|
|
49
86
|
let eventStep = model.getEvent(typeof flow.on === 'string' ? flow.on : (flow.on as any)?.eventName);
|
|
50
87
|
if (eventStep) {
|
|
51
|
-
eventStep = { ...eventStep }; // clone to avoid side effects
|
|
52
|
-
eventStep.defaultParams = {
|
|
88
|
+
eventStep = { ...eventStep } as any; // clone to avoid side effects
|
|
89
|
+
(eventStep as any).defaultParams = {
|
|
90
|
+
..._.get(flow, 'on.defaultParams', {}),
|
|
91
|
+
...(eventStep as any).defaultParams,
|
|
92
|
+
};
|
|
53
93
|
}
|
|
54
|
-
|
|
55
|
-
|
|
94
|
+
const stepDefs: Record<string, StepDefinition> = eventStep
|
|
95
|
+
? { eventStep: eventStep as any, ...flow.steps }
|
|
96
|
+
: flow.steps;
|
|
56
97
|
|
|
57
98
|
// Setup steps meta and runtime mapping
|
|
58
99
|
setupRuntimeContextSteps(flowContext, stepDefs, model, flowKey);
|
|
59
100
|
const stepsRuntime = flowContext.steps as Record<string, { params: any; uiSchema?: any; result?: any }>;
|
|
60
101
|
|
|
61
|
-
for (const stepKey
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
let handler: ActionDefinition['handler'] | undefined;
|
|
102
|
+
for (const [stepKey, step] of Object.entries(stepDefs) as [string, StepDefinition][]) {
|
|
103
|
+
// Resolve handler and params
|
|
104
|
+
let handler: ActionDefinition<FlowModel, FlowRuntimeContext>['handler'] | undefined;
|
|
65
105
|
let combinedParams: Record<string, any> = {};
|
|
66
|
-
let actionDefinition: ActionDefinition | undefined;
|
|
67
106
|
let useRawParams: StepDefinition['useRawParams'] = step.useRawParams;
|
|
68
|
-
|
|
107
|
+
let runtimeCtx: FlowRuntimeContext;
|
|
69
108
|
if (step.use) {
|
|
70
|
-
|
|
71
|
-
actionDefinition = model.getAction(step.use);
|
|
109
|
+
const actionDefinition = model.getAction(step.use);
|
|
72
110
|
if (!actionDefinition) {
|
|
73
111
|
flowContext.logger.error(
|
|
74
112
|
`BaseModel.applyFlow: Action '${step.use}' not found for step '${stepKey}' in flow '${flowKey}'. Skipping.`,
|
|
75
113
|
);
|
|
76
114
|
continue;
|
|
77
115
|
}
|
|
116
|
+
|
|
117
|
+
// 为当前 step 创建“临时上下文”,并直接注入 action 与 step 提供的定义(step 覆盖 action)
|
|
118
|
+
runtimeCtx = await createEphemeralContext<FlowRuntimeContext>(flowContext, {
|
|
119
|
+
...actionDefinition,
|
|
120
|
+
...step,
|
|
121
|
+
});
|
|
122
|
+
|
|
78
123
|
handler = step.handler || actionDefinition.handler;
|
|
79
124
|
useRawParams = useRawParams ?? actionDefinition.useRawParams;
|
|
80
|
-
const actionDefaultParams = await resolveDefaultParams(actionDefinition.defaultParams,
|
|
81
|
-
const stepDefaultParams = await resolveDefaultParams(step.defaultParams,
|
|
125
|
+
const actionDefaultParams = await resolveDefaultParams(actionDefinition.defaultParams, runtimeCtx);
|
|
126
|
+
const stepDefaultParams = await resolveDefaultParams(step.defaultParams, runtimeCtx);
|
|
82
127
|
combinedParams = { ...actionDefaultParams, ...stepDefaultParams };
|
|
83
128
|
} else if (step.handler) {
|
|
129
|
+
// 对于内联 handler,为该步创建临时上下文并注入 step 定义
|
|
130
|
+
runtimeCtx = await createEphemeralContext<FlowRuntimeContext>(flowContext, step);
|
|
84
131
|
handler = step.handler;
|
|
85
|
-
const stepDefaultParams = await resolveDefaultParams(step.defaultParams,
|
|
132
|
+
const stepDefaultParams = await resolveDefaultParams(step.defaultParams, runtimeCtx);
|
|
86
133
|
combinedParams = { ...stepDefaultParams };
|
|
87
134
|
} else {
|
|
88
135
|
flowContext.logger.error(
|
|
@@ -97,12 +144,11 @@ export class FlowExecutor {
|
|
|
97
144
|
}
|
|
98
145
|
if (typeof useRawParams === 'function') {
|
|
99
146
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
100
|
-
useRawParams = await useRawParams(
|
|
147
|
+
useRawParams = await useRawParams(runtimeCtx);
|
|
101
148
|
}
|
|
102
149
|
if (!useRawParams) {
|
|
103
|
-
combinedParams = await
|
|
150
|
+
combinedParams = await runtimeCtx.resolveJsonTemplate(combinedParams);
|
|
104
151
|
}
|
|
105
|
-
|
|
106
152
|
try {
|
|
107
153
|
if (!handler) {
|
|
108
154
|
flowContext.logger.error(
|
|
@@ -110,13 +156,12 @@ export class FlowExecutor {
|
|
|
110
156
|
);
|
|
111
157
|
continue;
|
|
112
158
|
}
|
|
113
|
-
const currentStepResult = handler(
|
|
159
|
+
const currentStepResult = handler(runtimeCtx, combinedParams);
|
|
114
160
|
const isAwait = step.isAwait !== false;
|
|
115
161
|
lastResult = isAwait ? await currentStepResult : currentStepResult;
|
|
116
162
|
|
|
117
|
-
// Store step result
|
|
163
|
+
// Store step result and update context
|
|
118
164
|
stepResults[stepKey] = lastResult;
|
|
119
|
-
// update the context
|
|
120
165
|
stepsRuntime[stepKey].result = stepResults[stepKey];
|
|
121
166
|
} catch (error) {
|
|
122
167
|
if (error instanceof FlowExitException) {
|
|
@@ -125,7 +170,6 @@ export class FlowExecutor {
|
|
|
125
170
|
}
|
|
126
171
|
if (error instanceof FlowExitAllException) {
|
|
127
172
|
flowContext.logger.info(`[FlowEngine] ${error.message}`);
|
|
128
|
-
// 传递特殊控制信号,让上层可中止后续流程
|
|
129
173
|
return Promise.resolve(error);
|
|
130
174
|
}
|
|
131
175
|
flowContext.logger.error(
|
|
@@ -138,119 +182,132 @@ export class FlowExecutor {
|
|
|
138
182
|
return Promise.resolve(stepResults);
|
|
139
183
|
}
|
|
140
184
|
|
|
185
|
+
// runAutoFlows 已移除:统一通过 dispatchEvent('beforeRender') + useCache 控制
|
|
186
|
+
|
|
141
187
|
/**
|
|
142
|
-
*
|
|
188
|
+
* Dispatch an event to flows bound via flow.on and execute them.
|
|
143
189
|
*/
|
|
144
|
-
async
|
|
145
|
-
|
|
190
|
+
async dispatchEvent(
|
|
191
|
+
model: FlowModel,
|
|
192
|
+
eventName: string,
|
|
193
|
+
inputArgs?: Record<string, any>,
|
|
194
|
+
options?: DispatchEventOptions,
|
|
195
|
+
): Promise<any> {
|
|
196
|
+
const isBeforeRender = eventName === 'beforeRender';
|
|
197
|
+
// 由模型层决定缺省值;执行器仅按显式 options 执行
|
|
198
|
+
const sequential = !!options?.sequential;
|
|
199
|
+
const useCache = !!options?.useCache;
|
|
200
|
+
// beforeRender 特殊处理:出错时一律抛出(用于错误边界捕获)
|
|
201
|
+
const throwOnError = isBeforeRender;
|
|
146
202
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return [];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const cacheKey = useCache
|
|
153
|
-
? FlowEngine.generateApplyFlowCacheKey(model.getAutoFlowCacheScope(), 'all', model.uid)
|
|
154
|
-
: null;
|
|
203
|
+
const runId = `${model.uid}-${eventName}-${Date.now()}`;
|
|
204
|
+
const logger = model.context.logger;
|
|
155
205
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
206
|
+
try {
|
|
207
|
+
await model.onDispatchEventStart?.(eventName, options, inputArgs);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
if (isBeforeRender && err instanceof FlowExitException) {
|
|
210
|
+
logger.debug(`[FlowModel.dispatchEvent] ${err.message}`);
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
// 进入错误钩子并记录
|
|
214
|
+
try {
|
|
215
|
+
await model.onDispatchEventError?.(eventName, options, inputArgs, err as Error);
|
|
216
|
+
} finally {
|
|
217
|
+
logger.error({ err }, `BaseModel.dispatchEvent: Start hook error for event '${eventName}'`);
|
|
165
218
|
}
|
|
219
|
+
if (throwOnError) throw err;
|
|
220
|
+
return;
|
|
166
221
|
}
|
|
167
222
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
logger.
|
|
192
|
-
|
|
223
|
+
// 构造待执行的 flows 列表
|
|
224
|
+
const flows = isBeforeRender
|
|
225
|
+
? model.getEventFlows('beforeRender') // beforeRender 事件集合(兼容未声明 on 且非 manual 的定义)
|
|
226
|
+
: Array.from(model.getFlows().values()).filter((flow) => {
|
|
227
|
+
const on = flow.on;
|
|
228
|
+
if (!on) return false;
|
|
229
|
+
if (typeof on === 'string') return on === eventName;
|
|
230
|
+
if (typeof on === 'object') return on.eventName === eventName;
|
|
231
|
+
return false;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// 组装执行函数(返回值用于缓存;beforeRender 返回 results:any[],其它返回 true)
|
|
235
|
+
const execute = async () => {
|
|
236
|
+
if (sequential) {
|
|
237
|
+
const ordered = flows.slice().sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0));
|
|
238
|
+
const results: any[] = [];
|
|
239
|
+
for (const flow of ordered) {
|
|
240
|
+
try {
|
|
241
|
+
logger.debug(
|
|
242
|
+
`BaseModel '${model.uid}' dispatching event '${eventName}' to flow '${flow.key}' (sequential).`,
|
|
243
|
+
);
|
|
244
|
+
const result = await this.runFlow(model, flow.key, inputArgs, runId);
|
|
245
|
+
if (result instanceof FlowExitAllException) {
|
|
246
|
+
logger.debug(`[FlowEngine.dispatchEvent] ${result.message}`);
|
|
247
|
+
break; // 终止后续
|
|
193
248
|
}
|
|
249
|
+
results.push(result);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
logger.error(
|
|
252
|
+
{ err: error },
|
|
253
|
+
`BaseModel.dispatchEvent: Error executing event-triggered flow '${flow.key}' for event '${eventName}' (sequential):`,
|
|
254
|
+
);
|
|
255
|
+
throw error;
|
|
194
256
|
}
|
|
195
257
|
}
|
|
196
258
|
return results;
|
|
197
|
-
} catch (error) {
|
|
198
|
-
if (error instanceof FlowExitException) {
|
|
199
|
-
logger.debug(`[FlowEngine.applyAutoFlows] ${error.message}`);
|
|
200
|
-
return results;
|
|
201
|
-
}
|
|
202
|
-
throw error;
|
|
203
259
|
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
if (!cacheKey || !this.engine) {
|
|
207
|
-
return await executeAutoFlows();
|
|
208
|
-
}
|
|
209
260
|
|
|
210
|
-
|
|
211
|
-
.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
261
|
+
// 并行
|
|
262
|
+
const results = await Promise.all(
|
|
263
|
+
flows.map(async (flow) => {
|
|
264
|
+
logger.debug(`BaseModel '${model.uid}' dispatching event '${eventName}' to flow '${flow.key}'.`);
|
|
265
|
+
try {
|
|
266
|
+
return await this.runFlow(model, flow.key, inputArgs, runId);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
logger.error(
|
|
269
|
+
{ err: error },
|
|
270
|
+
`BaseModel.dispatchEvent: Error executing event-triggered flow '${flow.key}' for event '${eventName}':`,
|
|
271
|
+
);
|
|
272
|
+
if (throwOnError) throw error;
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
return results.filter((x) => x !== undefined);
|
|
278
|
+
};
|
|
227
279
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
280
|
+
// 缓存键:按事件+scope 统一管理(beforeRender 也使用事件名 beforeRender)
|
|
281
|
+
const argsKey = useCache ? JSON.stringify(inputArgs ?? {}) : '';
|
|
282
|
+
const cacheKey = useCache
|
|
283
|
+
? FlowEngine.generateApplyFlowCacheKey(
|
|
284
|
+
`event:${model.getFlowCacheScope(eventName)}:${argsKey}`,
|
|
285
|
+
eventName,
|
|
286
|
+
model.uid,
|
|
287
|
+
)
|
|
288
|
+
: null;
|
|
231
289
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
await Promise.all(promises);
|
|
290
|
+
try {
|
|
291
|
+
const result = await this.withApplyFlowCache(cacheKey, execute);
|
|
292
|
+
// 事件结束钩子
|
|
293
|
+
try {
|
|
294
|
+
await model.onDispatchEventEnd?.(eventName, options, inputArgs, result);
|
|
295
|
+
} catch (hookErr) {
|
|
296
|
+
logger.error({ err: hookErr }, `BaseModel.dispatchEvent: End hook error for event '${eventName}'`);
|
|
297
|
+
}
|
|
298
|
+
return result;
|
|
299
|
+
} catch (error) {
|
|
300
|
+
// 进入错误钩子并记录
|
|
301
|
+
try {
|
|
302
|
+
await model.onDispatchEventError?.(eventName, options, inputArgs, error as Error);
|
|
303
|
+
} catch (_) {
|
|
304
|
+
// swallow secondary hook error
|
|
305
|
+
}
|
|
306
|
+
model.context.logger.error(
|
|
307
|
+
{ err: error },
|
|
308
|
+
`BaseModel.dispatchEvent: Error executing event '${eventName}' for model '${model.uid}':`,
|
|
309
|
+
);
|
|
310
|
+
if (throwOnError) throw error;
|
|
311
|
+
}
|
|
255
312
|
}
|
|
256
313
|
}
|
|
@@ -0,0 +1,197 @@
|
|
|
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, vi, beforeEach } from 'vitest';
|
|
11
|
+
import { FlowEngine } from '../../flowEngine';
|
|
12
|
+
import { FlowModel } from '../../models';
|
|
13
|
+
import type { FlowDefinitionOptions, FlowModelOptions } from '../../types';
|
|
14
|
+
|
|
15
|
+
describe('defineProperties/defineMethods injection', () => {
|
|
16
|
+
let engine: FlowEngine;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
engine = new FlowEngine();
|
|
20
|
+
vi.restoreAllMocks();
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('engine.context.runAction applies defs before defaultParams and handler', async () => {
|
|
25
|
+
const handler = vi.fn((_ctx, params) => params);
|
|
26
|
+
engine.registerActions({
|
|
27
|
+
test: {
|
|
28
|
+
name: 'test',
|
|
29
|
+
defineProperties: { foo: { value: 5 } },
|
|
30
|
+
defineMethods: { add: (x: number) => x + 1 },
|
|
31
|
+
defaultParams: (ctx) => ({ a: (ctx as any).foo, b: (ctx as any).add(2) }),
|
|
32
|
+
handler,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const result = await (engine.context as any).runAction('test');
|
|
37
|
+
expect(handler).toHaveBeenCalledTimes(1);
|
|
38
|
+
expect(result).toEqual({ a: 5, b: 3 });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('model.context.runAction applies defs before defaultParams and handler', async () => {
|
|
42
|
+
class M extends FlowModel {}
|
|
43
|
+
engine.registerModels({ M });
|
|
44
|
+
const h = vi.fn((_ctx, params) => ({ ...params, y: (_ctx as any).mul(3) }));
|
|
45
|
+
M.registerAction({
|
|
46
|
+
name: 'mAction',
|
|
47
|
+
defineProperties: async () => ({ al: { value: 7 } }),
|
|
48
|
+
defineMethods: async () => ({ mul: (x: number) => x * 2 }),
|
|
49
|
+
defaultParams: (ctx) => ({ a: (ctx as any).al }),
|
|
50
|
+
handler: h,
|
|
51
|
+
});
|
|
52
|
+
const m = engine.createModel<M>({ use: 'M' });
|
|
53
|
+
const res = await (m.context as any).runAction('mAction', { x: 3 });
|
|
54
|
+
expect(h).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(res).toEqual({ a: 7, x: 3, y: 6 });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
function createModelWithFlows(uid: string, flows: Record<string, Omit<FlowDefinitionOptions, 'key'>>) {
|
|
59
|
+
const model = new FlowModel({
|
|
60
|
+
uid,
|
|
61
|
+
flowEngine: engine,
|
|
62
|
+
stepParams: {},
|
|
63
|
+
subModels: {},
|
|
64
|
+
flowRegistry: flows,
|
|
65
|
+
} as FlowModelOptions);
|
|
66
|
+
return model;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
it('FlowExecutor: action-based step injects defs before defaultParams/handler', async () => {
|
|
70
|
+
const stepHandler = vi.fn((_ctx, params) => params);
|
|
71
|
+
engine.registerActions({
|
|
72
|
+
act: {
|
|
73
|
+
name: 'act',
|
|
74
|
+
defineProperties: { base: { value: 10 } },
|
|
75
|
+
defineMethods: { inc: (x: number) => x + 1 },
|
|
76
|
+
handler: stepHandler,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const flows = {
|
|
81
|
+
f: {
|
|
82
|
+
steps: {
|
|
83
|
+
s: {
|
|
84
|
+
use: 'act',
|
|
85
|
+
defaultParams: (ctx) => ({ p: (ctx as any).base, q: (ctx as any).inc(4) }),
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
} satisfies Record<string, Omit<FlowDefinitionOptions, 'key'>>;
|
|
90
|
+
|
|
91
|
+
const m = createModelWithFlows('m1', flows);
|
|
92
|
+
const res = await engine.executor.runFlow(m, 'f');
|
|
93
|
+
expect(stepHandler).toHaveBeenCalledTimes(1);
|
|
94
|
+
const [, received] = stepHandler.mock.calls[0];
|
|
95
|
+
expect(received).toEqual({ p: 10, q: 5 });
|
|
96
|
+
expect(res.s).toEqual({ p: 10, q: 5 });
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('FlowExecutor: inline step injects defs before defaultParams/handler', async () => {
|
|
100
|
+
const stepHandler = vi.fn((_ctx, params) => ({ ...params, v: (_ctx as any).twice(5) }));
|
|
101
|
+
const flows = {
|
|
102
|
+
f: {
|
|
103
|
+
steps: {
|
|
104
|
+
s: {
|
|
105
|
+
defineProperties: { k: { value: 8 } },
|
|
106
|
+
defineMethods: { twice: (x: number) => 2 * x },
|
|
107
|
+
defaultParams: (ctx) => ({ m: (ctx as any).k }),
|
|
108
|
+
handler: stepHandler,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
} satisfies Record<string, Omit<FlowDefinitionOptions, 'key'>>;
|
|
113
|
+
|
|
114
|
+
const m = createModelWithFlows('m2', flows);
|
|
115
|
+
const res = await engine.executor.runFlow(m, 'f');
|
|
116
|
+
expect(stepHandler).toHaveBeenCalledTimes(1);
|
|
117
|
+
const [, received] = stepHandler.mock.calls[0];
|
|
118
|
+
// params 仅包含 defaultParams 合并后的值;v 是 handler 计算的返回值
|
|
119
|
+
expect(received).toEqual({ m: 8 });
|
|
120
|
+
expect(res.s).toEqual({ m: 8, v: 10 });
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('FlowExecutor: step defs are isolated per step', async () => {
|
|
124
|
+
const flows = {
|
|
125
|
+
f: {
|
|
126
|
+
steps: {
|
|
127
|
+
a: {
|
|
128
|
+
defineMethods: { only: (x: number) => x + 1 },
|
|
129
|
+
handler: (_ctx, _params) => ({ ok: true }),
|
|
130
|
+
},
|
|
131
|
+
b: {
|
|
132
|
+
// 这里期望无法访问到上一步注入的方法,从而抛出错误
|
|
133
|
+
defaultParams: (ctx) => ({ v: (ctx as any).only(1) }),
|
|
134
|
+
handler: (_ctx, params) => params,
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
} satisfies Record<string, Omit<FlowDefinitionOptions, 'key'>>;
|
|
139
|
+
const m = createModelWithFlows('m-isolation', flows);
|
|
140
|
+
const res = await engine.executor.runFlow(m, 'f');
|
|
141
|
+
// a 正常执行,b 无法访问到 a 注入的方法,defaultParams 出错被 resolveDefaultParams 捕获后为空对象
|
|
142
|
+
expect(res).toEqual({ a: { ok: true }, b: {} });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('FlowExecutor: step defs override action defs when same key', async () => {
|
|
146
|
+
const stepHandler = vi.fn((_ctx, params) => params);
|
|
147
|
+
engine.registerActions({
|
|
148
|
+
act: {
|
|
149
|
+
name: 'act',
|
|
150
|
+
defineProperties: { foo: { value: 1 } },
|
|
151
|
+
defineMethods: { id: (x: number) => x },
|
|
152
|
+
handler: stepHandler,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
const flows = {
|
|
156
|
+
f: {
|
|
157
|
+
steps: {
|
|
158
|
+
s: {
|
|
159
|
+
use: 'act',
|
|
160
|
+
defineProperties: { foo: { value: 2 } },
|
|
161
|
+
defineMethods: { id: (x: number) => x + 100 },
|
|
162
|
+
defaultParams: (ctx) => ({ a: (ctx as any).foo, b: (ctx as any).id(1) }),
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
} satisfies Record<string, Omit<FlowDefinitionOptions, 'key'>>;
|
|
167
|
+
const m = createModelWithFlows('m3', flows);
|
|
168
|
+
await engine.executor.runFlow(m, 'f');
|
|
169
|
+
const [, received] = stepHandler.mock.calls[0];
|
|
170
|
+
expect(received).toEqual({ a: 2, b: 101 });
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('FlowExecutor: subsequent defineProperty/defineMethod write to parent context (not scoped)', async () => {
|
|
174
|
+
const flows = {
|
|
175
|
+
f: {
|
|
176
|
+
steps: {
|
|
177
|
+
a: {
|
|
178
|
+
handler: (ctx) => {
|
|
179
|
+
(ctx as any).defineProperty('mark', { value: 7 });
|
|
180
|
+
(ctx as any).defineMethod('inc', (x: number) => x + 1);
|
|
181
|
+
return { ok: true };
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
b: {
|
|
185
|
+
// 无注入,直接读取上一步通过 defineProperty/defineMethod 挂在到父级的能力
|
|
186
|
+
defaultParams: (ctx) => ({ v: (ctx as any).mark, w: (ctx as any).inc(2) }),
|
|
187
|
+
handler: (_ctx, params) => params,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
} satisfies Record<string, Omit<FlowDefinitionOptions, 'key'>>;
|
|
192
|
+
|
|
193
|
+
const m = engine.createModel<FlowModel>({ use: FlowModel.name, flowRegistry: flows });
|
|
194
|
+
const res = await engine.executor.runFlow(m, 'f');
|
|
195
|
+
expect(res).toEqual({ a: { ok: true }, b: { v: 7, w: 3 } });
|
|
196
|
+
});
|
|
197
|
+
});
|