@nocobase/flow-engine 2.0.0-alpha.2
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/LICENSE +661 -0
- package/README.md +30 -0
- package/lib/ContextPathProxy.d.ts +17 -0
- package/lib/ContextPathProxy.js +65 -0
- package/lib/ElementProxy.d.ts +17 -0
- package/lib/ElementProxy.js +93 -0
- package/lib/FlowContextProvider.d.ts +24 -0
- package/lib/FlowContextProvider.js +82 -0
- package/lib/FlowDefinition.d.ts +423 -0
- package/lib/FlowDefinition.js +257 -0
- package/lib/JSRunner.d.ts +32 -0
- package/lib/JSRunner.js +95 -0
- package/lib/ReactView.d.ts +20 -0
- package/lib/ReactView.js +120 -0
- package/lib/ViewScopedFlowEngine.d.ts +23 -0
- package/lib/ViewScopedFlowEngine.js +81 -0
- package/lib/acl/Acl.d.ts +31 -0
- package/lib/acl/Acl.js +115 -0
- package/lib/action-registry/BaseActionRegistry.d.ts +23 -0
- package/lib/action-registry/BaseActionRegistry.js +57 -0
- package/lib/action-registry/EngineActionRegistry.d.ts +20 -0
- package/lib/action-registry/EngineActionRegistry.js +47 -0
- package/lib/action-registry/ModelActionRegistry.d.ts +34 -0
- package/lib/action-registry/ModelActionRegistry.js +79 -0
- package/lib/components/DynamicFlowsEditor.d.ts +17 -0
- package/lib/components/DynamicFlowsEditor.js +49 -0
- package/lib/components/FieldModelRenderer.d.ts +10 -0
- package/lib/components/FieldModelRenderer.js +94 -0
- package/lib/components/FlowContextSelector.d.ts +11 -0
- package/lib/components/FlowContextSelector.js +221 -0
- package/lib/components/FlowErrorFallback.d.ts +25 -0
- package/lib/components/FlowErrorFallback.js +264 -0
- package/lib/components/FlowModelRenderer.d.ts +64 -0
- package/lib/components/FlowModelRenderer.js +254 -0
- package/lib/components/FormItem.d.ts +18 -0
- package/lib/components/FormItem.js +147 -0
- package/lib/components/common/FlowSettingsButton.d.ts +11 -0
- package/lib/components/common/FlowSettingsButton.js +66 -0
- package/lib/components/common/index.d.ts +9 -0
- package/lib/components/common/index.js +30 -0
- package/lib/components/common/withFlowDesignMode.d.ts +26 -0
- package/lib/components/common/withFlowDesignMode.js +61 -0
- package/lib/components/dnd/getMousePositionOnElement.d.ts +50 -0
- package/lib/components/dnd/getMousePositionOnElement.js +95 -0
- package/lib/components/dnd/index.d.ts +24 -0
- package/lib/components/dnd/index.js +164 -0
- package/lib/components/dnd/moveBlock.d.ts +33 -0
- package/lib/components/dnd/moveBlock.js +302 -0
- package/lib/components/index.d.ts +18 -0
- package/lib/components/index.js +48 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.d.ts +46 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +225 -0
- package/lib/components/settings/independents/dropdown/index.d.ts +9 -0
- package/lib/components/settings/independents/dropdown/index.js +30 -0
- package/lib/components/settings/independents/index.d.ts +1 -0
- package/lib/components/settings/independents/index.js +30 -0
- package/lib/components/settings/index.d.ts +10 -0
- package/lib/components/settings/index.js +32 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +24 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +501 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.d.ts +45 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +231 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +111 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +484 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.d.ts +26 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.js +342 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.d.ts +23 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.js +110 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +206 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.js +47 -0
- package/lib/components/settings/wrappers/contextual/index.d.ts +14 -0
- package/lib/components/settings/wrappers/contextual/index.js +40 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.d.ts +33 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +207 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.d.ts +41 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +84 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.d.ts +16 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +88 -0
- package/lib/components/settings/wrappers/embedded/index.d.ts +10 -0
- package/lib/components/settings/wrappers/embedded/index.js +32 -0
- package/lib/components/settings/wrappers/index.d.ts +2 -0
- package/lib/components/settings/wrappers/index.js +32 -0
- package/lib/components/subModel/AddSubModelButton.d.ts +62 -0
- package/lib/components/subModel/AddSubModelButton.js +415 -0
- package/lib/components/subModel/LazyDropdown.d.ts +55 -0
- package/lib/components/subModel/LazyDropdown.js +524 -0
- package/lib/components/subModel/index.d.ts +10 -0
- package/lib/components/subModel/index.js +32 -0
- package/lib/components/subModel/utils.d.ts +34 -0
- package/lib/components/subModel/utils.js +287 -0
- package/lib/components/variables/InlineVariableTag.d.ts +21 -0
- package/lib/components/variables/InlineVariableTag.js +123 -0
- package/lib/components/variables/SlateVariableEditor.d.ts +46 -0
- package/lib/components/variables/SlateVariableEditor.js +302 -0
- package/lib/components/variables/VariableInput.d.ts +11 -0
- package/lib/components/variables/VariableInput.js +322 -0
- package/lib/components/variables/VariableTag.d.ts +11 -0
- package/lib/components/variables/VariableTag.js +148 -0
- package/lib/components/variables/VariableTrigger.d.ts +20 -0
- package/lib/components/variables/VariableTrigger.js +136 -0
- package/lib/components/variables/index.d.ts +15 -0
- package/lib/components/variables/index.js +53 -0
- package/lib/components/variables/types.d.ts +93 -0
- package/lib/components/variables/types.js +24 -0
- package/lib/components/variables/useResolvedMetaTree.d.ts +19 -0
- package/lib/components/variables/useResolvedMetaTree.js +91 -0
- package/lib/components/variables/utils.d.ts +22 -0
- package/lib/components/variables/utils.js +177 -0
- package/lib/data-source/index.d.ts +180 -0
- package/lib/data-source/index.js +733 -0
- package/lib/data-source/jioToJoiSchema.d.ts +19 -0
- package/lib/data-source/jioToJoiSchema.js +114 -0
- package/lib/decorators/index.d.ts +9 -0
- package/lib/decorators/index.js +36 -0
- package/lib/decorators/largeField.d.ts +9 -0
- package/lib/decorators/largeField.js +42 -0
- package/lib/emitter.d.ts +16 -0
- package/lib/emitter.js +58 -0
- package/lib/event-registry/BaseEventRegistry.d.ts +22 -0
- package/lib/event-registry/BaseEventRegistry.js +57 -0
- package/lib/event-registry/EngineEventRegistry.d.ts +19 -0
- package/lib/event-registry/EngineEventRegistry.js +47 -0
- package/lib/event-registry/ModelEventRegistry.d.ts +33 -0
- package/lib/event-registry/ModelEventRegistry.js +79 -0
- package/lib/executor/FlowExecutor.d.ts +26 -0
- package/lib/executor/FlowExecutor.js +262 -0
- package/lib/flow-registry/BaseFlowRegistry.d.ts +46 -0
- package/lib/flow-registry/BaseFlowRegistry.js +86 -0
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +22 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +95 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +21 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +59 -0
- package/lib/flow-registry/index.d.ts +11 -0
- package/lib/flow-registry/index.js +34 -0
- package/lib/flowContext.d.ts +215 -0
- package/lib/flowContext.js +1266 -0
- package/lib/flowEngine.d.ts +340 -0
- package/lib/flowEngine.js +781 -0
- package/lib/flowI18n.d.ts +46 -0
- package/lib/flowI18n.js +117 -0
- package/lib/flowSettings.d.ts +266 -0
- package/lib/flowSettings.js +850 -0
- package/lib/hooks/index.d.ts +14 -0
- package/lib/hooks/index.js +40 -0
- package/lib/hooks/useApplyAutoFlows.d.ts +21 -0
- package/lib/hooks/useApplyAutoFlows.js +62 -0
- package/lib/hooks/useFlowModel.d.ts +29 -0
- package/lib/hooks/useFlowModel.js +72 -0
- package/lib/hooks/useFlowModelById.d.ts +11 -0
- package/lib/hooks/useFlowModelById.js +61 -0
- package/lib/hooks/useFlowSettingsContext.d.ts +20 -0
- package/lib/hooks/useFlowSettingsContext.js +61 -0
- package/lib/hooks/useFlowStep.d.ts +17 -0
- package/lib/hooks/useFlowStep.js +56 -0
- package/lib/hooks/useNiceDropdownMaxHeight.d.ts +13 -0
- package/lib/hooks/useNiceDropdownMaxHeight.js +52 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.js +73 -0
- package/lib/locale/en-US.json +61 -0
- package/lib/locale/index.d.ts +141 -0
- package/lib/locale/index.js +70 -0
- package/lib/locale/zh-CN.json +61 -0
- package/lib/models/CollectionFieldModel.d.ts +50 -0
- package/lib/models/CollectionFieldModel.js +242 -0
- package/lib/models/DisplayItemModel.d.ts +12 -0
- package/lib/models/DisplayItemModel.js +41 -0
- package/lib/models/EditableItemModel.d.ts +12 -0
- package/lib/models/EditableItemModel.js +41 -0
- package/lib/models/FilterableItemModel.d.ts +12 -0
- package/lib/models/FilterableItemModel.js +41 -0
- package/lib/models/flowModel.d.ts +344 -0
- package/lib/models/flowModel.js +1133 -0
- package/lib/models/forkFlowModel.d.ts +83 -0
- package/lib/models/forkFlowModel.js +257 -0
- package/lib/models/index.d.ts +14 -0
- package/lib/models/index.js +40 -0
- package/lib/provider.d.ts +22 -0
- package/lib/provider.js +114 -0
- package/lib/resources/apiResource.d.ts +34 -0
- package/lib/resources/apiResource.js +153 -0
- package/lib/resources/baseRecordResource.d.ts +61 -0
- package/lib/resources/baseRecordResource.js +264 -0
- package/lib/resources/filterItem.d.ts +33 -0
- package/lib/resources/filterItem.js +93 -0
- package/lib/resources/flowResource.d.ts +45 -0
- package/lib/resources/flowResource.js +146 -0
- package/lib/resources/index.d.ts +15 -0
- package/lib/resources/index.js +42 -0
- package/lib/resources/multiRecordResource.d.ts +53 -0
- package/lib/resources/multiRecordResource.js +230 -0
- package/lib/resources/singleRecordResource.d.ts +23 -0
- package/lib/resources/singleRecordResource.js +111 -0
- package/lib/resources/sqlResource.d.ts +73 -0
- package/lib/resources/sqlResource.js +294 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +38 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.js +217 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +59 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +70 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +61 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +62 -0
- package/lib/runjs-context/helpers.d.ts +17 -0
- package/lib/runjs-context/helpers.js +79 -0
- package/lib/runjs-context/index.d.ts +19 -0
- package/lib/runjs-context/index.js +57 -0
- package/lib/runjs-context/registry.d.ts +17 -0
- package/lib/runjs-context/registry.js +93 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.js +46 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.js +41 -0
- package/lib/runjs-context/snippets/index.d.ts +11 -0
- package/lib/runjs-context/snippets/index.js +94 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +45 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.js +56 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.js +59 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.js +60 -0
- package/lib/runjs-context/snippets/types.d.ts +16 -0
- package/lib/runjs-context/snippets/types.js +24 -0
- package/lib/types.d.ts +398 -0
- package/lib/types.js +43 -0
- package/lib/utils/autoFlowError.d.ts +16 -0
- package/lib/utils/autoFlowError.js +53 -0
- package/lib/utils/constants.d.ts +29 -0
- package/lib/utils/constants.js +77 -0
- package/lib/utils/context.d.ts +40 -0
- package/lib/utils/context.js +63 -0
- package/lib/utils/createCollectionContextMeta.d.ts +11 -0
- package/lib/utils/createCollectionContextMeta.js +117 -0
- package/lib/utils/exceptions.d.ts +22 -0
- package/lib/utils/exceptions.js +62 -0
- package/lib/utils/flow-definitions.d.ts +11 -0
- package/lib/utils/flow-definitions.js +40 -0
- package/lib/utils/index.d.ts +22 -0
- package/lib/utils/index.js +117 -0
- package/lib/utils/inheritance.d.ts +16 -0
- package/lib/utils/inheritance.js +53 -0
- package/lib/utils/params-resolvers.d.ts +51 -0
- package/lib/utils/params-resolvers.js +309 -0
- package/lib/utils/parsePathnameToViewParams.d.ts +34 -0
- package/lib/utils/parsePathnameToViewParams.js +84 -0
- package/lib/utils/safeGlobals.d.ts +16 -0
- package/lib/utils/safeGlobals.js +179 -0
- package/lib/utils/schema-utils.d.ts +40 -0
- package/lib/utils/schema-utils.js +161 -0
- package/lib/utils/serverContextParams.d.ts +28 -0
- package/lib/utils/serverContextParams.js +106 -0
- package/lib/utils/setupRuntimeContextSteps.d.ts +19 -0
- package/lib/utils/setupRuntimeContextSteps.js +88 -0
- package/lib/utils/translation.d.ts +18 -0
- package/lib/utils/translation.js +58 -0
- package/lib/utils/variablesParams.d.ts +51 -0
- package/lib/utils/variablesParams.js +150 -0
- package/lib/views/DialogComponent.d.ts +22 -0
- package/lib/views/DialogComponent.js +98 -0
- package/lib/views/DrawerComponent.d.ts +11 -0
- package/lib/views/DrawerComponent.js +101 -0
- package/lib/views/FlowView.d.ts +76 -0
- package/lib/views/FlowView.js +81 -0
- package/lib/views/PageComponent.d.ts +10 -0
- package/lib/views/PageComponent.js +167 -0
- package/lib/views/ViewNavigation.d.ts +45 -0
- package/lib/views/ViewNavigation.js +97 -0
- package/lib/views/createViewMeta.d.ts +16 -0
- package/lib/views/createViewMeta.js +171 -0
- package/lib/views/index.d.ts +13 -0
- package/lib/views/index.js +48 -0
- package/lib/views/useDialog.d.ts +32 -0
- package/lib/views/useDialog.js +199 -0
- package/lib/views/useDrawer.d.ts +33 -0
- package/lib/views/useDrawer.js +206 -0
- package/lib/views/usePage.d.ts +32 -0
- package/lib/views/usePage.js +193 -0
- package/lib/views/usePatchElement.d.ts +10 -0
- package/lib/views/usePatchElement.js +54 -0
- package/lib/views/usePopover.d.ts +17 -0
- package/lib/views/usePopover.js +159 -0
- package/package.json +37 -0
- package/src/ContextPathProxy.ts +45 -0
- package/src/ElementProxy.ts +69 -0
- package/src/FlowContextProvider.tsx +40 -0
- package/src/FlowDefinition.ts +275 -0
- package/src/JSRunner.ts +84 -0
- package/src/ReactView.tsx +104 -0
- package/src/ViewScopedFlowEngine.ts +75 -0
- package/src/__tests__/ElementProxy.test.ts +51 -0
- package/src/__tests__/JSRunner.test.ts +92 -0
- package/src/__tests__/ReactView.test.tsx +63 -0
- package/src/__tests__/context-path-proxy.test.ts +35 -0
- package/src/__tests__/flow-engine.test.ts +189 -0
- package/src/__tests__/flowContext.test.ts +2012 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +171 -0
- package/src/__tests__/flowI18n.test.ts +28 -0
- package/src/__tests__/flowModel.getFlows.test.ts +61 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +78 -0
- package/src/__tests__/flowRuntimeContext.test.ts +187 -0
- package/src/__tests__/flowSettings.open.test.tsx +1920 -0
- package/src/__tests__/flowSettings.test.ts +566 -0
- package/src/__tests__/globalFlowRegistry.test.ts +77 -0
- package/src/__tests__/isFieldInterfaceMatch.test.ts +51 -0
- package/src/__tests__/metaTreeNodeCache.test.ts +234 -0
- package/src/__tests__/path-aggregation.test.ts +85 -0
- package/src/__tests__/provider.test.tsx +28 -0
- package/src/__tests__/renderHiddenInConfig.test.tsx +91 -0
- package/src/__tests__/runjsContext.test.ts +60 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +212 -0
- package/src/acl/Acl.tsx +109 -0
- package/src/acl/__tests__/Acl.test.tsx +72 -0
- package/src/action-registry/BaseActionRegistry.ts +46 -0
- package/src/action-registry/EngineActionRegistry.ts +32 -0
- package/src/action-registry/ModelActionRegistry.ts +75 -0
- package/src/action-registry/__tests__/engineActionRegistry.test.ts +43 -0
- package/src/action-registry/__tests__/modelActionRegistry.test.ts +107 -0
- package/src/components/DynamicFlowsEditor.tsx +318 -0
- package/src/components/FieldModelRenderer.tsx +62 -0
- package/src/components/FlowContextSelector.tsx +255 -0
- package/src/components/FlowErrorFallback.tsx +316 -0
- package/src/components/FlowModelRenderer.tsx +428 -0
- package/src/components/FormItem.tsx +130 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +226 -0
- package/src/components/common/FlowSettingsButton.tsx +30 -0
- package/src/components/common/index.ts +10 -0
- package/src/components/common/withFlowDesignMode.tsx +49 -0
- package/src/components/dnd/getMousePositionOnElement.ts +115 -0
- package/src/components/dnd/index.tsx +128 -0
- package/src/components/dnd/moveBlock.ts +379 -0
- package/src/components/index.ts +20 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +279 -0
- package/src/components/settings/independents/dropdown/index.ts +10 -0
- package/src/components/settings/independents/index.ts +2 -0
- package/src/components/settings/index.ts +11 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +617 -0
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +292 -0
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +655 -0
- package/src/components/settings/wrappers/contextual/StepRequiredSettingsDialog.tsx +446 -0
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +109 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +217 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDrawer.tsx +32 -0
- package/src/components/settings/wrappers/contextual/index.ts +15 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +258 -0
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +111 -0
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +96 -0
- package/src/components/settings/wrappers/embedded/index.ts +11 -0
- package/src/components/settings/wrappers/index.ts +5 -0
- package/src/components/subModel/AddSubModelButton.tsx +575 -0
- package/src/components/subModel/LazyDropdown.tsx +714 -0
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1185 -0
- package/src/components/subModel/__tests__/buildWrapperFieldChildren.test.ts +192 -0
- package/src/components/subModel/__tests__/utils.test.ts +425 -0
- package/src/components/subModel/index.ts +12 -0
- package/src/components/subModel/utils.ts +278 -0
- package/src/components/variables/InlineVariableTag.tsx +97 -0
- package/src/components/variables/SlateVariableEditor.tsx +384 -0
- package/src/components/variables/VariableInput.tsx +342 -0
- package/src/components/variables/VariableTag.tsx +123 -0
- package/src/components/variables/VariableTrigger.tsx +116 -0
- package/src/components/variables/__tests__/FlowContextSelector.test.tsx +553 -0
- package/src/components/variables/__tests__/VariableInput.test.tsx +550 -0
- package/src/components/variables/__tests__/VariableTag.test.tsx +347 -0
- package/src/components/variables/__tests__/test-utils.tsx +62 -0
- package/src/components/variables/__tests__/utils.test.ts +310 -0
- package/src/components/variables/index.ts +16 -0
- package/src/components/variables/types.ts +100 -0
- package/src/components/variables/useResolvedMetaTree.ts +76 -0
- package/src/components/variables/utils.ts +192 -0
- package/src/data-source/__tests__/collection.test.ts +58 -0
- package/src/data-source/__tests__/index.test.ts +82 -0
- package/src/data-source/__tests__/jioToJoiSchema.test.ts +56 -0
- package/src/data-source/index.ts +812 -0
- package/src/data-source/jioToJoiSchema.ts +103 -0
- package/src/decorators/index.ts +10 -0
- package/src/decorators/largeField.ts +14 -0
- package/src/emitter.ts +33 -0
- package/src/event-registry/BaseEventRegistry.ts +40 -0
- package/src/event-registry/EngineEventRegistry.ts +26 -0
- package/src/event-registry/ModelEventRegistry.ts +69 -0
- package/src/event-registry/__tests__/engineEventRegistry.test.ts +48 -0
- package/src/executor/FlowExecutor.ts +256 -0
- package/src/executor/__tests__/eventStep.test.ts +157 -0
- package/src/executor/__tests__/flowExecutor.test.ts +163 -0
- package/src/flow-registry/BaseFlowRegistry.ts +91 -0
- package/src/flow-registry/GlobalFlowRegistry.ts +82 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +39 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +141 -0
- package/src/flow-registry/__tests__/instance-and-global-registry.test.ts +67 -0
- package/src/flow-registry/__tests__/instanceFlowRegistry.test.ts +83 -0
- package/src/flow-registry/index.ts +12 -0
- package/src/flowContext.ts +1639 -0
- package/src/flowEngine.ts +905 -0
- package/src/flowI18n.ts +96 -0
- package/src/flowSettings.ts +1045 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/useApplyAutoFlows.ts +51 -0
- package/src/hooks/useFlowModel.tsx +59 -0
- package/src/hooks/useFlowModelById.ts +37 -0
- package/src/hooks/useFlowSettingsContext.tsx +37 -0
- package/src/hooks/useFlowStep.tsx +19 -0
- package/src/hooks/useNiceDropdownMaxHeight.ts +34 -0
- package/src/index.ts +38 -0
- package/src/locale/en-US.json +61 -0
- package/src/locale/index.ts +38 -0
- package/src/locale/zh-CN.json +61 -0
- package/src/models/CollectionFieldModel.tsx +269 -0
- package/src/models/DisplayItemModel.tsx +13 -0
- package/src/models/EditableItemModel.tsx +13 -0
- package/src/models/FilterableItemModel.tsx +13 -0
- package/src/models/__tests__/CollectionFieldModel.test.ts +122 -0
- package/src/models/__tests__/defaultParams-on-create.test.ts +83 -0
- package/src/models/__tests__/flow-model-oninit.test.ts +44 -0
- package/src/models/__tests__/flowModel.actions.integration.test.ts +100 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +100 -0
- package/src/models/__tests__/flowModel.test.ts +2746 -0
- package/src/models/__tests__/flowRegistry.test.ts +512 -0
- package/src/models/__tests__/forkFlowModel.test.ts +1047 -0
- package/src/models/__tests__/model-actions.test.ts +70 -0
- package/src/models/__tests__/model-events.test.ts +69 -0
- package/src/models/flowModel.tsx +1398 -0
- package/src/models/forkFlowModel.ts +287 -0
- package/src/models/index.ts +17 -0
- package/src/provider.tsx +101 -0
- package/src/resources/__tests__/apiResource.test.ts +201 -0
- package/src/resources/__tests__/baseRecordResource.test.ts +262 -0
- package/src/resources/__tests__/filterItem.test.ts +260 -0
- package/src/resources/__tests__/flowResource.test.ts +127 -0
- package/src/resources/apiResource.ts +148 -0
- package/src/resources/baseRecordResource.ts +279 -0
- package/src/resources/filterItem.ts +74 -0
- package/src/resources/flowResource.ts +143 -0
- package/src/resources/index.ts +17 -0
- package/src/resources/multiRecordResource.ts +219 -0
- package/src/resources/singleRecordResource.ts +83 -0
- package/src/resources/sqlResource.ts +299 -0
- package/src/runjs-context/contexts/FlowRunJSContext.ts +190 -0
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +52 -0
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +32 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +43 -0
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +34 -0
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +35 -0
- package/src/runjs-context/helpers.ts +56 -0
- package/src/runjs-context/index.ts +20 -0
- package/src/runjs-context/registry.ts +65 -0
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +19 -0
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +24 -0
- package/src/runjs-context/snippets/global/sleep.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +22 -0
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +23 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +19 -0
- package/src/runjs-context/snippets/index.ts +59 -0
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/actions/collection-selected-count.snippet.ts +22 -0
- package/src/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.ts +29 -0
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +30 -0
- package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +34 -0
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsitem/render-basic.snippet.ts +27 -0
- package/src/runjs-context/snippets/scene/linkage/set-disabled.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/set-field-value.snippet.ts +37 -0
- package/src/runjs-context/snippets/scene/linkage/set-required.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/toggle-visible.snippet.ts +38 -0
- package/src/runjs-context/snippets/types.ts +17 -0
- package/src/types.ts +474 -0
- package/src/utils/__tests__/context.test.ts +93 -0
- package/src/utils/__tests__/params-resolvers.test.ts +652 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +104 -0
- package/src/utils/__tests__/safeGlobals.test.ts +29 -0
- package/src/utils/__tests__/utils.test.ts +1021 -0
- package/src/utils/__tests__/variablesParams.test.ts +52 -0
- package/src/utils/autoFlowError.ts +29 -0
- package/src/utils/constants.ts +60 -0
- package/src/utils/context.ts +70 -0
- package/src/utils/createCollectionContextMeta.ts +122 -0
- package/src/utils/exceptions.ts +36 -0
- package/src/utils/flow-definitions.ts +16 -0
- package/src/utils/index.ts +63 -0
- package/src/utils/inheritance.ts +39 -0
- package/src/utils/params-resolvers.ts +482 -0
- package/src/utils/parsePathnameToViewParams.ts +103 -0
- package/src/utils/safeGlobals.ts +188 -0
- package/src/utils/schema-utils.ts +201 -0
- package/src/utils/serverContextParams.ts +111 -0
- package/src/utils/setupRuntimeContextSteps.ts +89 -0
- package/src/utils/translation.ts +37 -0
- package/src/utils/variablesParams.ts +175 -0
- package/src/views/DialogComponent.tsx +79 -0
- package/src/views/DrawerComponent.tsx +72 -0
- package/src/views/FlowView.tsx +103 -0
- package/src/views/PageComponent.tsx +150 -0
- package/src/views/ViewNavigation.ts +122 -0
- package/src/views/__tests__/FlowView.test.ts +31 -0
- package/src/views/__tests__/ViewNavigation.test.ts +191 -0
- package/src/views/__tests__/usePatchElement.test.tsx +28 -0
- package/src/views/createViewMeta.ts +157 -0
- package/src/views/index.tsx +14 -0
- package/src/views/useDialog.tsx +192 -0
- package/src/views/useDrawer.tsx +205 -0
- package/src/views/usePage.tsx +182 -0
- package/src/views/usePatchElement.tsx +27 -0
- package/src/views/usePopover.tsx +131 -0
|
@@ -0,0 +1,905 @@
|
|
|
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
|
+
import { observable } from '@formily/reactive';
|
|
10
|
+
import _ from 'lodash';
|
|
11
|
+
import pino from 'pino';
|
|
12
|
+
import { EngineActionRegistry } from './action-registry/EngineActionRegistry';
|
|
13
|
+
import { EngineEventRegistry } from './event-registry/EngineEventRegistry';
|
|
14
|
+
import { FlowExecutor } from './executor/FlowExecutor';
|
|
15
|
+
import { FlowContext, FlowEngineContext, FlowRuntimeContext } from './flowContext';
|
|
16
|
+
import { FlowSettings } from './flowSettings';
|
|
17
|
+
import { ErrorFlowModel, FlowModel } from './models';
|
|
18
|
+
import { ReactView } from './ReactView';
|
|
19
|
+
import { APIResource, FlowResource, MultiRecordResource, SingleRecordResource, SQLResource } from './resources';
|
|
20
|
+
import type {
|
|
21
|
+
ActionDefinition,
|
|
22
|
+
ApplyFlowCacheEntry,
|
|
23
|
+
CreateModelOptions,
|
|
24
|
+
EventDefinition,
|
|
25
|
+
FlowModelOptions,
|
|
26
|
+
IFlowModelRepository,
|
|
27
|
+
ModelConstructor,
|
|
28
|
+
PersistOptions,
|
|
29
|
+
ResourceType,
|
|
30
|
+
} from './types';
|
|
31
|
+
import { isInheritedFrom } from './utils';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* FlowEngine is the core class of the flow engine, responsible for managing flow models, actions, model repository, and more.
|
|
35
|
+
* It provides capabilities for registering, creating, finding, persisting, replacing, and moving models.
|
|
36
|
+
* Supports flow definitions, action definitions, model class inheritance and filtering.
|
|
37
|
+
* Integrates FlowEngineContext, FlowSettings, and ReactView for context, configuration, and view rendering.
|
|
38
|
+
*
|
|
39
|
+
* Main features:
|
|
40
|
+
* - Register, get, and find model classes and model instances
|
|
41
|
+
* - Register and get action definitions
|
|
42
|
+
* - Persist and query models via the model repository
|
|
43
|
+
* - Register flow definitions
|
|
44
|
+
* - Create, find, replace, move, and destroy model instances
|
|
45
|
+
* - Support for model class inheritance and filtering
|
|
46
|
+
* - Internationalization support
|
|
47
|
+
* - Integration with React view rendering
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const engine = new FlowEngine();
|
|
51
|
+
* engine.registerModels({ MyModel });
|
|
52
|
+
* engine.setModelRepository(new MyRepository());
|
|
53
|
+
* const model = engine.createModel({ use: 'MyModel', uid: 'xxx' });
|
|
54
|
+
*/
|
|
55
|
+
export class FlowEngine {
|
|
56
|
+
/**
|
|
57
|
+
* Global action registry
|
|
58
|
+
*/
|
|
59
|
+
private _actionRegistry = new EngineActionRegistry();
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Global event registry
|
|
63
|
+
*/
|
|
64
|
+
private _eventRegistry = new EngineEventRegistry();
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Registered model classes.
|
|
68
|
+
* Key is the model class name, value is the model class constructor.
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
private _modelClasses: Map<string, ModelConstructor> = observable.shallow(new Map());
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Created model instances.
|
|
75
|
+
* Key is the model instance UID, value is the model instance object.
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
private _modelInstances: Map<string, any> = new Map();
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The current model repository instance, implements IFlowModelRepository.
|
|
82
|
+
* Used for model persistence and queries.
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
private _modelRepository: IFlowModelRepository | null = null;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Flow application cache.
|
|
89
|
+
* Key is the cache key, value is ApplyFlowCacheEntry.
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
private _applyFlowCache = new Map<string, ApplyFlowCacheEntry>();
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Model saving state tracking.
|
|
96
|
+
* Key is the model UID, value is the save promise.
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
private _savingModels = new Map<string, Promise<any>>();
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Flow engine context object.
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
private _flowContext: FlowEngineContext;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 视图作用域引擎的栈式链表指针。
|
|
109
|
+
* - previousEngine:打开当前视图的上一个引擎
|
|
110
|
+
* - nextEngine:在当前之上的下一个引擎
|
|
111
|
+
*/
|
|
112
|
+
private _previousEngine?: FlowEngine;
|
|
113
|
+
private _nextEngine?: FlowEngine;
|
|
114
|
+
|
|
115
|
+
private _resources = new Map<string, typeof FlowResource>();
|
|
116
|
+
|
|
117
|
+
logger: pino.Logger;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Flow settings, including components and form scopes.
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
public flowSettings: FlowSettings;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Experimental API: Integrates React view rendering capability into FlowEngine.
|
|
127
|
+
* This property may change or be removed in the future. Use with caution.
|
|
128
|
+
* @experimental
|
|
129
|
+
* @public
|
|
130
|
+
*/
|
|
131
|
+
public reactView: ReactView;
|
|
132
|
+
/**
|
|
133
|
+
* Flow executor that runs flows and auto-flows.
|
|
134
|
+
*/
|
|
135
|
+
public executor: FlowExecutor;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Constructor. Initializes React view, registers default model and form scopes.
|
|
139
|
+
*/
|
|
140
|
+
constructor() {
|
|
141
|
+
this.reactView = new ReactView(this);
|
|
142
|
+
this.flowSettings = new FlowSettings(this);
|
|
143
|
+
this.flowSettings.registerScopes({ t: this.translate.bind(this) });
|
|
144
|
+
this.registerModels({ FlowModel }); // 会造成循环依赖问题,移除掉
|
|
145
|
+
this.registerResources({
|
|
146
|
+
FlowResource,
|
|
147
|
+
SQLResource,
|
|
148
|
+
APIResource,
|
|
149
|
+
SingleRecordResource,
|
|
150
|
+
MultiRecordResource,
|
|
151
|
+
});
|
|
152
|
+
this.logger = pino({
|
|
153
|
+
level: 'trace',
|
|
154
|
+
browser: {
|
|
155
|
+
write: {
|
|
156
|
+
fatal: (o) => console.trace(o),
|
|
157
|
+
error: (o) => console.error(o),
|
|
158
|
+
warn: (o) => console.warn(o),
|
|
159
|
+
info: (o) => console.info(o),
|
|
160
|
+
debug: (o) => console.debug(o),
|
|
161
|
+
trace: (o) => console.trace(o),
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
this.executor = new FlowExecutor(this);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** 上一个引擎(根引擎为 undefined) */
|
|
169
|
+
get previousEngine(): FlowEngine | undefined {
|
|
170
|
+
return this._previousEngine;
|
|
171
|
+
}
|
|
172
|
+
/** 下一个引擎(若存在) */
|
|
173
|
+
get nextEngine(): FlowEngine | undefined {
|
|
174
|
+
return this._nextEngine;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 将当前引擎链接到 prev 之后(用于视图打开时形成栈关系)。
|
|
179
|
+
*/
|
|
180
|
+
public linkAfter(engine: FlowEngine): void {
|
|
181
|
+
// 找到栈底
|
|
182
|
+
let prev: FlowEngine = engine;
|
|
183
|
+
while (prev._nextEngine) prev = prev._nextEngine;
|
|
184
|
+
this._previousEngine = prev;
|
|
185
|
+
if (prev) {
|
|
186
|
+
prev._nextEngine = this;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 将当前引擎从栈中移除并修复相邻指针(用于视图关闭时)。
|
|
192
|
+
*/
|
|
193
|
+
public unlinkFromStack(): void {
|
|
194
|
+
const prev = this._previousEngine;
|
|
195
|
+
const next = this._nextEngine;
|
|
196
|
+
if (prev) {
|
|
197
|
+
prev._nextEngine = undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// (已移除)getModelGlobal/forEachModelGlobal/getAllModelsGlobal:不再维护冗余全局遍历 API
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get the flow engine context object.
|
|
205
|
+
* @returns {FlowEngineContext} Flow engine context
|
|
206
|
+
*/
|
|
207
|
+
get context() {
|
|
208
|
+
if (!this._flowContext) {
|
|
209
|
+
this._flowContext = new FlowEngineContext(this);
|
|
210
|
+
}
|
|
211
|
+
return this._flowContext;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
get dataSourceManager() {
|
|
215
|
+
return this.context.dataSourceManager;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get the flow application cache.
|
|
220
|
+
* @returns {Map<string, ApplyFlowCacheEntry>} Flow application cache map
|
|
221
|
+
* @internal
|
|
222
|
+
*/
|
|
223
|
+
get applyFlowCache() {
|
|
224
|
+
return this._applyFlowCache;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Set the model repository for persisting and querying model instances.
|
|
229
|
+
* If a model repository was already set, it will be overwritten and a warning will be printed.
|
|
230
|
+
* @param {IFlowModelRepository} modelRepository The model repository instance implementing IFlowModelRepository.
|
|
231
|
+
* @example
|
|
232
|
+
* flowEngine.setModelRepository(new MyFlowModelRepository());
|
|
233
|
+
*/
|
|
234
|
+
setModelRepository(modelRepository: IFlowModelRepository) {
|
|
235
|
+
if (this._modelRepository) {
|
|
236
|
+
console.warn('FlowEngine: Model repository is already set and will be overwritten.');
|
|
237
|
+
}
|
|
238
|
+
this._modelRepository = modelRepository;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
get modelRepository(): IFlowModelRepository | null {
|
|
242
|
+
return this._modelRepository;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Internationalization translation method, calls the context's t method.
|
|
247
|
+
* @param {string} keyOrTemplate Translation key or template string
|
|
248
|
+
* @param {any} [options] Optional parameters
|
|
249
|
+
* @returns {string} Translated string
|
|
250
|
+
*/
|
|
251
|
+
translate(keyOrTemplate: string, options?: any): string {
|
|
252
|
+
return this.context.t(keyOrTemplate, options);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Register multiple actions.
|
|
257
|
+
* @param {Record<string, ActionDefinition>} actions Action definition object collection
|
|
258
|
+
*/
|
|
259
|
+
registerActions(actions: Record<string, ActionDefinition>): void {
|
|
260
|
+
this._actionRegistry.registerActions(actions);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get a registered action definition.
|
|
265
|
+
* @template TModel Specific FlowModel subclass type
|
|
266
|
+
* @param {string} name Action name
|
|
267
|
+
* @returns {ActionDefinition<TModel> | undefined} Action definition, or undefined if not found
|
|
268
|
+
*/
|
|
269
|
+
public getAction<TModel extends FlowModel = FlowModel, TCtx extends FlowContext = FlowRuntimeContext<TModel>>(
|
|
270
|
+
name: string,
|
|
271
|
+
): ActionDefinition<TModel, TCtx> | undefined {
|
|
272
|
+
return this._actionRegistry.getAction<TModel, TCtx>(name);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Get all registered global actions.
|
|
277
|
+
* Returns a new Map to avoid external mutation of internal state.
|
|
278
|
+
*/
|
|
279
|
+
public getActions<TModel extends FlowModel = FlowModel, TCtx extends FlowContext = FlowRuntimeContext<TModel>>(): Map<
|
|
280
|
+
string,
|
|
281
|
+
ActionDefinition<TModel, TCtx>
|
|
282
|
+
> {
|
|
283
|
+
return this._actionRegistry.getActions<TModel, TCtx>();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Register multiple events.
|
|
288
|
+
*/
|
|
289
|
+
registerEvents(events: Record<string, EventDefinition>): void {
|
|
290
|
+
this._eventRegistry.registerEvents(events);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get a registered event definition.
|
|
295
|
+
*/
|
|
296
|
+
public getEvent<TModel extends FlowModel = FlowModel>(name: string): EventDefinition<TModel> | undefined {
|
|
297
|
+
return this._eventRegistry.getEvent<TModel>(name);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get all registered global events.
|
|
302
|
+
*/
|
|
303
|
+
public getEvents<TModel extends FlowModel = FlowModel>(): Map<string, EventDefinition<TModel>> {
|
|
304
|
+
return this._eventRegistry.getEvents<TModel>();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Register a single model class.
|
|
309
|
+
* @param {string} name Model class name
|
|
310
|
+
* @param {ModelConstructor} modelClass Model class constructor
|
|
311
|
+
* @private
|
|
312
|
+
*/
|
|
313
|
+
#registerModel(name: string, modelClass: ModelConstructor): void {
|
|
314
|
+
if (this._modelClasses.has(name)) {
|
|
315
|
+
console.warn(`FlowEngine: Model class with name '${name}' is already registered and will be overwritten.`);
|
|
316
|
+
}
|
|
317
|
+
Object.defineProperty(modelClass, 'name', { value: name });
|
|
318
|
+
this._modelClasses.set(name, modelClass);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Register multiple model classes.
|
|
323
|
+
* @param {Record<string, ModelConstructor>} models Model class map, key is model name, value is model constructor
|
|
324
|
+
* @returns {void}
|
|
325
|
+
* @example
|
|
326
|
+
* flowEngine.registerModels({ UserModel, OrderModel });
|
|
327
|
+
*/
|
|
328
|
+
public registerModels(models: Record<string, ModelConstructor | typeof FlowModel<any>>) {
|
|
329
|
+
for (const [name, modelClass] of Object.entries(models)) {
|
|
330
|
+
this.#registerModel(name, modelClass);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
registerResources(resources: Record<string, any>) {
|
|
335
|
+
for (const [name, resourceClass] of Object.entries(resources)) {
|
|
336
|
+
this._resources.set(name, resourceClass);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
createResource<T = FlowResource>(resourceType: ResourceType<T>, options?: { context?: FlowContext }): T {
|
|
341
|
+
if (typeof resourceType === 'string') {
|
|
342
|
+
const ResourceClass = this._resources.get(resourceType);
|
|
343
|
+
if (!ResourceClass) {
|
|
344
|
+
throw new Error(`Resource class '${resourceType}' not found. Please register it first.`);
|
|
345
|
+
}
|
|
346
|
+
return new ResourceClass((options?.context as any) || this.context) as T;
|
|
347
|
+
}
|
|
348
|
+
const R = resourceType;
|
|
349
|
+
return new R(options?.context || this.context) as T;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get all registered model classes.
|
|
354
|
+
* @returns {Map<string, ModelConstructor>} Model class map
|
|
355
|
+
*/
|
|
356
|
+
getModelClasses() {
|
|
357
|
+
return this._modelClasses;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get a registered model class (constructor).
|
|
362
|
+
* @param {string} name Model class name
|
|
363
|
+
* @returns {ModelConstructor | undefined} Model constructor, or undefined if not found
|
|
364
|
+
*/
|
|
365
|
+
public getModelClass(name: string): ModelConstructor | undefined {
|
|
366
|
+
return this._modelClasses.get(name);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Find a registered model class by predicate.
|
|
371
|
+
* @param predicate Callback function, arguments are (name, ModelClass), returns true if matched
|
|
372
|
+
* @returns {[string, ModelConstructor] | undefined} Matched model class and name
|
|
373
|
+
*/
|
|
374
|
+
public findModelClass(
|
|
375
|
+
predicate: (name: string, ModelClass: ModelConstructor) => boolean,
|
|
376
|
+
): [string, ModelConstructor] | undefined {
|
|
377
|
+
for (const [name, ModelClass] of this._modelClasses) {
|
|
378
|
+
if (predicate(name, ModelClass)) {
|
|
379
|
+
return [name, ModelClass];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return undefined;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Filter model classes by base class (supports multi-level inheritance), with optional custom filter.
|
|
387
|
+
* @param {string | ModelConstructor} baseClass Base class name or constructor
|
|
388
|
+
* @param {(ModelClass: ModelConstructor, className: string) => boolean} [filter] Optional filter function
|
|
389
|
+
* @returns {Map<string, ModelConstructor>} Model classes inherited from base class and passed the filter
|
|
390
|
+
*/
|
|
391
|
+
public getSubclassesOf(
|
|
392
|
+
baseClass: string | ModelConstructor,
|
|
393
|
+
filter?: (ModelClass: ModelConstructor, className: string) => boolean,
|
|
394
|
+
): Map<string, ModelConstructor> {
|
|
395
|
+
const parentModelClass = typeof baseClass === 'string' ? this.getModelClass(baseClass) : baseClass;
|
|
396
|
+
const result = new Map<string, ModelConstructor>();
|
|
397
|
+
if (!parentModelClass) return result;
|
|
398
|
+
for (const [className, ModelClass] of this._modelClasses) {
|
|
399
|
+
if (isInheritedFrom(ModelClass, parentModelClass)) {
|
|
400
|
+
if (!filter || filter(ModelClass, className)) {
|
|
401
|
+
result.set(className, ModelClass);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return result;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Create and register a model instance.
|
|
410
|
+
* If an instance with the same UID exists, returns the existing instance.
|
|
411
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
412
|
+
* @param {CreateModelOptions} options Model creation options
|
|
413
|
+
* @returns {T} Created model instance
|
|
414
|
+
*/
|
|
415
|
+
public createModel<T extends FlowModel = FlowModel>(
|
|
416
|
+
options: CreateModelOptions,
|
|
417
|
+
extra?: { delegateToParent?: boolean; delegate?: FlowContext },
|
|
418
|
+
): T {
|
|
419
|
+
const { parentId, uid, use: modelClassName, subModels } = options;
|
|
420
|
+
const ModelClass = typeof modelClassName === 'string' ? this.getModelClass(modelClassName) : modelClassName;
|
|
421
|
+
|
|
422
|
+
if (uid && this._modelInstances.has(uid)) {
|
|
423
|
+
return this._modelInstances.get(uid) as T;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
let modelInstance: T | ErrorFlowModel;
|
|
427
|
+
|
|
428
|
+
if (!ModelClass) {
|
|
429
|
+
modelInstance = new ErrorFlowModel({ ...options, flowEngine: this } as any);
|
|
430
|
+
modelInstance.setErrorMessage(`Model class '${modelClassName}' not found. Please register it first.`);
|
|
431
|
+
} else {
|
|
432
|
+
modelInstance = new (ModelClass as ModelConstructor<T>)({ ...options, flowEngine: this } as any);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (extra?.delegate) {
|
|
436
|
+
modelInstance.context.addDelegate(extra.delegate);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (parentId && this._modelInstances.has(parentId)) {
|
|
440
|
+
modelInstance.setParent(this._modelInstances.get(parentId));
|
|
441
|
+
if (extra?.delegateToParent === false) {
|
|
442
|
+
modelInstance.removeParentDelegate();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
this._modelInstances.set(modelInstance.uid, modelInstance);
|
|
447
|
+
|
|
448
|
+
modelInstance.onInit(options);
|
|
449
|
+
|
|
450
|
+
// 在模型实例化阶段应用 flow 级 defaultParams(仅填充缺失的 stepParams,不覆盖)
|
|
451
|
+
// 不阻塞创建流程:允许 defaultParams 为异步函数
|
|
452
|
+
this._applyFlowDefinitionDefaultParams(modelInstance as FlowModel).catch((err) => {
|
|
453
|
+
console.warn('FlowEngine: apply flow defaultParams failed:', err);
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
modelInstance._createSubModels(options.subModels);
|
|
457
|
+
|
|
458
|
+
return modelInstance as T;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* 尝试应用当前模型可用 flow 的 defaultParams(如果存在)到 model.stepParams。
|
|
463
|
+
* 仅对尚未存在的步骤参数进行填充,不覆盖已有值。
|
|
464
|
+
*/
|
|
465
|
+
async _applyFlowDefinitionDefaultParams(model: FlowModel) {
|
|
466
|
+
try {
|
|
467
|
+
const flows = model.getFlows();
|
|
468
|
+
if (!flows || flows.size === 0) return;
|
|
469
|
+
const ctx = model.context;
|
|
470
|
+
for (const [flowKey, flowDef] of flows.entries()) {
|
|
471
|
+
const dp = flowDef.defaultParams;
|
|
472
|
+
if (!dp) continue;
|
|
473
|
+
|
|
474
|
+
let resolved: any;
|
|
475
|
+
try {
|
|
476
|
+
resolved = typeof dp === 'function' ? await dp(ctx) : dp;
|
|
477
|
+
} catch (e) {
|
|
478
|
+
console.warn(`FlowEngine: resolve defaultParams of flow '${flowKey}' failed:`, e);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (!resolved || typeof resolved !== 'object') continue;
|
|
483
|
+
|
|
484
|
+
// 仅支持:返回当前 flow 的步骤对象 { [stepKey]: params }
|
|
485
|
+
const stepsMap = (flowDef as any).getSteps?.() as Map<string, any> | undefined;
|
|
486
|
+
const stepKeys = stepsMap ? Array.from(stepsMap.keys()) : Object.keys(flowDef.steps || {});
|
|
487
|
+
const entries = Object.entries(resolved).filter(([k]) => stepKeys.includes(k));
|
|
488
|
+
if (entries.length === 0) continue;
|
|
489
|
+
|
|
490
|
+
for (const [stepKey, params] of entries) {
|
|
491
|
+
const exists = model.getStepParams(flowKey, stepKey as string);
|
|
492
|
+
if (exists === undefined && params && typeof params === 'object') {
|
|
493
|
+
model.setStepParams(flowKey, stepKey as string, params as any);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} catch (error) {
|
|
498
|
+
console.warn('FlowEngine: apply flow defaultParams error:', error);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Get a model instance by UID.
|
|
504
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
505
|
+
* @param {string} uid Model instance UID
|
|
506
|
+
* @returns {T | undefined} Model instance, or undefined if not found
|
|
507
|
+
*/
|
|
508
|
+
public getModel<T extends FlowModel = FlowModel>(uid: string, global?: boolean): T | undefined {
|
|
509
|
+
// 默认仅在当前引擎查找;只有当 global === true 时才跨视图栈查找
|
|
510
|
+
if (!global) {
|
|
511
|
+
return this._modelInstances.get(uid) as T | undefined;
|
|
512
|
+
}
|
|
513
|
+
// 跨视图栈查找:按视图栈从栈顶到根逐个查找
|
|
514
|
+
// 1) 找到栈顶引擎
|
|
515
|
+
let top: FlowEngine = this;
|
|
516
|
+
while (top.nextEngine) top = top.nextEngine;
|
|
517
|
+
// 2) 从栈顶向下查找,命中即返回
|
|
518
|
+
let eng: FlowEngine | undefined = top;
|
|
519
|
+
while (eng) {
|
|
520
|
+
const found = eng._modelInstances.get(uid) as T | undefined;
|
|
521
|
+
if (found) return found;
|
|
522
|
+
eng = eng.previousEngine;
|
|
523
|
+
}
|
|
524
|
+
return undefined;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Iterate all registered model instances.
|
|
529
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
530
|
+
* @param {(model: T) => void} callback Callback function
|
|
531
|
+
*/
|
|
532
|
+
forEachModel<T extends FlowModel = FlowModel>(callback: (model: T) => void): void {
|
|
533
|
+
this._modelInstances.forEach(callback);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Remove a local model instance.
|
|
538
|
+
* @param {string} uid UID of the model instance to destroy
|
|
539
|
+
* @returns {boolean} Returns true if successfully destroyed, false otherwise (e.g. instance does not exist)
|
|
540
|
+
*/
|
|
541
|
+
public removeModel(uid: string): boolean {
|
|
542
|
+
if (!this._modelInstances.has(uid)) {
|
|
543
|
+
console.warn(`FlowEngine: Model with UID '${uid}' does not exist.`);
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
const modelInstance = this._modelInstances.get(uid) as FlowModel;
|
|
547
|
+
modelInstance.clearForks();
|
|
548
|
+
// 从父模型中移除当前模型的引用
|
|
549
|
+
if (modelInstance.parent?.subModels) {
|
|
550
|
+
for (const subKey in modelInstance.parent.subModels) {
|
|
551
|
+
const subModelValue = modelInstance.parent.subModels[subKey];
|
|
552
|
+
|
|
553
|
+
if (Array.isArray(subModelValue)) {
|
|
554
|
+
const index = subModelValue.findIndex((subModel) => subModel == modelInstance);
|
|
555
|
+
if (index !== -1) {
|
|
556
|
+
subModelValue.splice(index, 1);
|
|
557
|
+
modelInstance.parent.emitter.emit('onSubModelRemoved', modelInstance);
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
} else if (subModelValue && subModelValue === modelInstance) {
|
|
561
|
+
delete modelInstance.parent.subModels[subKey];
|
|
562
|
+
modelInstance.parent.emitter.emit('onSubModelRemoved', modelInstance);
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
this._modelInstances.delete(uid);
|
|
568
|
+
return true;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Check if the model repository is set.
|
|
573
|
+
* @returns {boolean} Returns true if set, false otherwise.
|
|
574
|
+
* @private
|
|
575
|
+
*/
|
|
576
|
+
private ensureModelRepository(): boolean {
|
|
577
|
+
if (!this._modelRepository) {
|
|
578
|
+
// 不抛错,直接返回 false
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Load a model instance (prefers local, falls back to repository).
|
|
586
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
587
|
+
* @param {any} options Load options
|
|
588
|
+
* @returns {Promise<T | null>} Loaded model instance or null
|
|
589
|
+
*/
|
|
590
|
+
async loadModel<T extends FlowModel = FlowModel>(options): Promise<T | null> {
|
|
591
|
+
if (!this.ensureModelRepository()) return;
|
|
592
|
+
const model = this.findModelByParentId(options.parentId, options.subKey);
|
|
593
|
+
if (model) {
|
|
594
|
+
return model as T;
|
|
595
|
+
}
|
|
596
|
+
const data = await this._modelRepository.findOne(options);
|
|
597
|
+
return data?.uid ? this.createModel<T>(data as any) : null;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Find a sub-model by parent model ID and subKey.
|
|
602
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
603
|
+
* @param {string} parentId Parent model UID
|
|
604
|
+
* @param {string} subKey Sub-model key
|
|
605
|
+
* @returns {T | null} Found sub-model or null
|
|
606
|
+
*/
|
|
607
|
+
findModelByParentId<T extends FlowModel = FlowModel>(parentId: string, subKey: string): T | null {
|
|
608
|
+
if (parentId && this._modelInstances.has(parentId)) {
|
|
609
|
+
const parentModel = this._modelInstances.get(parentId) as FlowModel;
|
|
610
|
+
if (parentModel && parentModel.subModels[subKey]) {
|
|
611
|
+
const subModels = parentModel.subModels[subKey];
|
|
612
|
+
if (Array.isArray(subModels)) {
|
|
613
|
+
return subModels[0] as T; // 返回第一个子模型
|
|
614
|
+
} else {
|
|
615
|
+
return subModels as T;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Load or create a model instance.
|
|
623
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
624
|
+
* @param {any} options Load or create options
|
|
625
|
+
* @returns {Promise<T | null>} Model instance or null
|
|
626
|
+
*/
|
|
627
|
+
async loadOrCreateModel<T extends FlowModel = FlowModel>(
|
|
628
|
+
options,
|
|
629
|
+
extra?: {
|
|
630
|
+
delegateToParent?: boolean;
|
|
631
|
+
delegate?: FlowContext;
|
|
632
|
+
},
|
|
633
|
+
): Promise<T | null> {
|
|
634
|
+
if (!this.ensureModelRepository()) return;
|
|
635
|
+
const { uid, parentId, subKey } = options;
|
|
636
|
+
if (uid && this._modelInstances.has(uid)) {
|
|
637
|
+
return this._modelInstances.get(uid) as T;
|
|
638
|
+
}
|
|
639
|
+
const m = this.findModelByParentId<T>(parentId, subKey);
|
|
640
|
+
if (m) {
|
|
641
|
+
return m;
|
|
642
|
+
}
|
|
643
|
+
const data = await this._modelRepository.findOne(options);
|
|
644
|
+
let model: T | null = null;
|
|
645
|
+
if (data?.uid) {
|
|
646
|
+
model = this.createModel<T>(data as any, extra);
|
|
647
|
+
} else {
|
|
648
|
+
model = this.createModel<T>(options, extra);
|
|
649
|
+
await model.save();
|
|
650
|
+
}
|
|
651
|
+
if (model.parent) {
|
|
652
|
+
const subModel = model.parent.findSubModel(model.subKey, (m) => {
|
|
653
|
+
return m.uid === model.uid;
|
|
654
|
+
});
|
|
655
|
+
if (subModel) {
|
|
656
|
+
return model;
|
|
657
|
+
}
|
|
658
|
+
if (model.subType === 'array') {
|
|
659
|
+
model.parent.addSubModel(model.subKey, model);
|
|
660
|
+
} else {
|
|
661
|
+
model.parent.setSubModel(model.subKey, model);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return model;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Persist and save a model instance.
|
|
669
|
+
* Prevents concurrent saves of the same model by tracking save operations.
|
|
670
|
+
* If a model is already being saved, subsequent calls will wait for the existing save to complete.
|
|
671
|
+
*
|
|
672
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
673
|
+
* @param {T} model Model instance to save
|
|
674
|
+
* @param {object} [options] Save options
|
|
675
|
+
* @param {boolean} [options.onlyStepParams] Whether to save only step parameters
|
|
676
|
+
* @returns {Promise<any>} Repository save result
|
|
677
|
+
*/
|
|
678
|
+
async saveModel<T extends FlowModel = FlowModel>(model: T, options?: { onlyStepParams?: boolean }): Promise<any> {
|
|
679
|
+
if (!this.ensureModelRepository()) return;
|
|
680
|
+
|
|
681
|
+
const modelUid = model.uid;
|
|
682
|
+
|
|
683
|
+
// 如果这个 model 正在保存中,返回现有的保存 Promise
|
|
684
|
+
if (this._savingModels.has(modelUid)) {
|
|
685
|
+
this.logger.debug(`Model ${modelUid} is already being saved, waiting for existing save operation`);
|
|
686
|
+
return await this._savingModels.get(modelUid);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// 创建保存 Promise 并添加到追踪 Map 中
|
|
690
|
+
const savePromise = this._performModelSave(model, options);
|
|
691
|
+
this._savingModels.set(modelUid, savePromise);
|
|
692
|
+
|
|
693
|
+
try {
|
|
694
|
+
const result = await savePromise;
|
|
695
|
+
return result;
|
|
696
|
+
} finally {
|
|
697
|
+
// 无论成功还是失败,都要清除保存状态
|
|
698
|
+
this._savingModels.delete(modelUid);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Perform the actual model save operation.
|
|
704
|
+
* @template T FlowModel subclass type, defaults to FlowModel.
|
|
705
|
+
* @param {T} model Model instance to save
|
|
706
|
+
* @param {object} [options] Save options
|
|
707
|
+
* @returns {Promise<any>} Repository save result
|
|
708
|
+
* @private
|
|
709
|
+
*/
|
|
710
|
+
async _performModelSave<T extends FlowModel = FlowModel>(
|
|
711
|
+
model: T,
|
|
712
|
+
options?: { onlyStepParams?: boolean },
|
|
713
|
+
): Promise<any> {
|
|
714
|
+
this.logger.debug(`Starting save operation for model ${model.uid}`);
|
|
715
|
+
try {
|
|
716
|
+
const result = await this._modelRepository.save(model, options);
|
|
717
|
+
this.logger.debug(`Successfully saved model ${model.uid}`);
|
|
718
|
+
return result;
|
|
719
|
+
} catch (error) {
|
|
720
|
+
this.logger.error(`Failed to save model ${model.uid}:`, error);
|
|
721
|
+
throw error;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Destroy a model instance (persistently delete and remove local instance).
|
|
727
|
+
* @param {string} uid UID of the model to destroy
|
|
728
|
+
* @returns {Promise<boolean>} Whether destroyed successfully
|
|
729
|
+
*/
|
|
730
|
+
async destroyModel(uid: string) {
|
|
731
|
+
if (this.ensureModelRepository()) {
|
|
732
|
+
await this._modelRepository.destroy(uid);
|
|
733
|
+
}
|
|
734
|
+
return this.removeModel(uid);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Replace a model instance with a new instance of a class.
|
|
739
|
+
* @template T New model type
|
|
740
|
+
* @param {string} uid UID of the model to replace
|
|
741
|
+
* @param {Partial<FlowModelOptions> | ((oldModel: FlowModel) => Partial<FlowModelOptions>)} [optionsOrFn]
|
|
742
|
+
* Options for creating the new model, supports two forms:
|
|
743
|
+
* 1. Pass options directly
|
|
744
|
+
* 2. Pass a function that receives current options and returns new options
|
|
745
|
+
* @returns {Promise<T | null>} Newly created model instance
|
|
746
|
+
*/
|
|
747
|
+
async replaceModel<T extends FlowModel = FlowModel>(
|
|
748
|
+
uid: string,
|
|
749
|
+
optionsOrFn?: Partial<FlowModelOptions> | ((currentOptions: FlowModelOptions) => Partial<FlowModelOptions>),
|
|
750
|
+
): Promise<T | null> {
|
|
751
|
+
const oldModel = this.getModel(uid);
|
|
752
|
+
if (!oldModel) {
|
|
753
|
+
console.warn(`FlowEngine: Cannot replace model. Model with UID '${uid}' not found.`);
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// 1. 保存当前模型的关键信息
|
|
758
|
+
const currentParent = oldModel.parent;
|
|
759
|
+
const currentSubKey = oldModel.subKey;
|
|
760
|
+
const currentSubType = oldModel.subType;
|
|
761
|
+
const currentOptions = oldModel.serialize();
|
|
762
|
+
|
|
763
|
+
// 2. 确定新的选项
|
|
764
|
+
let userOptions: Partial<FlowModelOptions>;
|
|
765
|
+
|
|
766
|
+
if (typeof optionsOrFn === 'function') {
|
|
767
|
+
// 函数模式:传入当前options,获取新的options
|
|
768
|
+
userOptions = optionsOrFn(oldModel as any);
|
|
769
|
+
} else {
|
|
770
|
+
// 对象模式:直接使用提供的options替换
|
|
771
|
+
userOptions = optionsOrFn || {};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// 3. 合并用户选项和关键属性
|
|
775
|
+
const newOptions = {
|
|
776
|
+
..._.omit(currentOptions, ['subModels']),
|
|
777
|
+
...userOptions,
|
|
778
|
+
} as CreateModelOptions;
|
|
779
|
+
|
|
780
|
+
// 暂停父模型的事件触发,
|
|
781
|
+
// TODO: find a better way to do this
|
|
782
|
+
if (currentParent) {
|
|
783
|
+
currentParent.emitter.setPaused(true);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// 4. 销毁当前模型(这会处理所有清理工作:持久化删除、内存清理、父模型引用等)
|
|
787
|
+
await oldModel.destroy();
|
|
788
|
+
|
|
789
|
+
// 5. 使用createModel创建新的模型实例
|
|
790
|
+
const newModel = this.createModel<T>(newOptions);
|
|
791
|
+
|
|
792
|
+
// 6. 如果有父模型,将新模型添加到父模型的subModels中
|
|
793
|
+
if (currentParent && currentSubKey) {
|
|
794
|
+
if (currentSubType === 'array') {
|
|
795
|
+
// 对于数组类型,使用addSubModel方法
|
|
796
|
+
currentParent.addSubModel(currentSubKey, newModel);
|
|
797
|
+
} else {
|
|
798
|
+
// 对于对象类型,使用setSubModel方法
|
|
799
|
+
currentParent.setSubModel(currentSubKey, newModel);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// 7. 触发事件以通知其他部分模型已替换
|
|
804
|
+
if (currentParent) {
|
|
805
|
+
currentParent.emitter.setPaused(false);
|
|
806
|
+
currentParent.parent.invalidateAutoFlowCache(true);
|
|
807
|
+
currentParent.parent?.rerender();
|
|
808
|
+
currentParent.emitter.emit('onSubModelReplaced', { oldModel, newModel });
|
|
809
|
+
}
|
|
810
|
+
await newModel.save();
|
|
811
|
+
return newModel;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Move a model instance within its parent model.
|
|
816
|
+
* @param {any} sourceId Source model UID
|
|
817
|
+
* @param {any} targetId Target model UID
|
|
818
|
+
* @returns {Promise<void>} No return value
|
|
819
|
+
*/
|
|
820
|
+
async moveModel(sourceId: any, targetId: any, options?: PersistOptions): Promise<void> {
|
|
821
|
+
const sourceModel = this.getModel(sourceId);
|
|
822
|
+
const targetModel = this.getModel(targetId);
|
|
823
|
+
if (!sourceModel || !targetModel) {
|
|
824
|
+
console.warn(`FlowEngine: Cannot move model. Source or target model not found.`);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const move = (sourceModel: FlowModel, targetModel: FlowModel) => {
|
|
828
|
+
if (!sourceModel.parent || !targetModel.parent || sourceModel.parent !== targetModel.parent) {
|
|
829
|
+
console.error('FlowModel.moveTo: Both models must have the same parent to perform move operation.');
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const subModels = sourceModel.parent.subModels[sourceModel.subKey];
|
|
834
|
+
|
|
835
|
+
if (!subModels || !Array.isArray(subModels)) {
|
|
836
|
+
console.error('FlowModel.moveTo: Parent subModels must be an array to perform move operation.');
|
|
837
|
+
return false;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const findIndex = (model: FlowModel) => subModels.findIndex((item) => item.uid === model.uid);
|
|
841
|
+
|
|
842
|
+
const currentIndex = findIndex(sourceModel);
|
|
843
|
+
const targetIndex = findIndex(targetModel);
|
|
844
|
+
|
|
845
|
+
if (currentIndex === -1 || targetIndex === -1) {
|
|
846
|
+
console.error('FlowModel.moveTo: Current or target model not found in parent subModels.');
|
|
847
|
+
return false;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
if (currentIndex === targetIndex) {
|
|
851
|
+
console.warn('FlowModel.moveTo: Current model is already at the target position. No action taken.');
|
|
852
|
+
return false;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// 使用splice直接移动数组元素(O(n)比排序O(n log n)更快)
|
|
856
|
+
const [movedModel] = subModels.splice(currentIndex, 1);
|
|
857
|
+
subModels.splice(targetIndex, 0, movedModel);
|
|
858
|
+
|
|
859
|
+
// 重新分配连续的sortIndex
|
|
860
|
+
subModels.forEach((model, index) => {
|
|
861
|
+
model.sortIndex = index;
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
return true;
|
|
865
|
+
};
|
|
866
|
+
move(sourceModel, targetModel);
|
|
867
|
+
if (options?.persist !== false && this.ensureModelRepository()) {
|
|
868
|
+
const position = sourceModel.sortIndex - targetModel.sortIndex > 0 ? 'after' : 'before';
|
|
869
|
+
await this._modelRepository.move(sourceId, targetId, position);
|
|
870
|
+
}
|
|
871
|
+
// 触发事件以通知其他部分模型已移动
|
|
872
|
+
sourceModel.parent.emitter.emit('onSubModelMoved', { source: sourceModel, target: targetModel });
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Filter model classes by parent class (supports multi-level inheritance).
|
|
877
|
+
* @param {string | ModelConstructor} parentClass Parent class name or constructor
|
|
878
|
+
* @returns {Map<string, ModelConstructor>} Model classes inherited from the specified parent class
|
|
879
|
+
*/
|
|
880
|
+
public filterModelClassByParent(parentClass: string | ModelConstructor) {
|
|
881
|
+
const parentModelClass = typeof parentClass === 'string' ? this.getModelClass(parentClass) : parentClass;
|
|
882
|
+
if (!parentModelClass) {
|
|
883
|
+
return new Map();
|
|
884
|
+
}
|
|
885
|
+
const modelClasses = new Map<string, ModelConstructor>();
|
|
886
|
+
for (const [className, ModelClass] of this._modelClasses) {
|
|
887
|
+
if (isInheritedFrom(ModelClass, parentModelClass)) {
|
|
888
|
+
modelClasses.set(className, ModelClass);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return modelClasses;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Generate a unique key for the flow application cache.
|
|
896
|
+
* @param {string} prefix Prefix
|
|
897
|
+
* @param {string} flowKey Flow key
|
|
898
|
+
* @param {string} modelUid Model UID
|
|
899
|
+
* @returns {string} Unique cache key
|
|
900
|
+
* @internal
|
|
901
|
+
*/
|
|
902
|
+
static generateApplyFlowCacheKey(prefix: string, flowKey: string, modelUid: string): string {
|
|
903
|
+
return `${prefix}:${flowKey}:${modelUid}`;
|
|
904
|
+
}
|
|
905
|
+
}
|