@nocobase/flow-engine 2.0.0-alpha.7 → 2.0.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/BlockScopedFlowEngine.d.ts +23 -0
- package/lib/BlockScopedFlowEngine.js +91 -0
- package/lib/FlowContextProvider.d.ts +2 -2
- package/lib/FlowContextProvider.js +3 -3
- package/lib/FlowDefinition.d.ts +6 -4
- package/lib/JSRunner.d.ts +6 -0
- package/lib/JSRunner.js +27 -1
- package/lib/ViewScopedFlowEngine.d.ts +1 -1
- package/lib/ViewScopedFlowEngine.js +18 -1
- package/lib/acl/Acl.d.ts +12 -12
- package/lib/acl/Acl.js +88 -30
- package/lib/components/DynamicFlowsEditor.js +2 -4
- package/lib/components/FieldModelRenderer.js +17 -9
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +19 -3
- package/lib/components/FlowModelRenderer.d.ts +4 -6
- package/lib/components/FlowModelRenderer.js +35 -53
- package/lib/components/FormItem.js +5 -1
- package/lib/components/MobilePopup.d.ts +20 -0
- package/lib/components/MobilePopup.js +102 -0
- package/lib/components/MobilePopup.style.d.ts +17 -0
- package/lib/components/MobilePopup.style.js +186 -0
- package/lib/components/common/withFlowDesignMode.d.ts +1 -1
- package/lib/components/common/withFlowDesignMode.js +5 -5
- package/lib/components/dnd/gridDragPlanner.d.ts +1 -0
- package/lib/components/dnd/gridDragPlanner.js +53 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +3 -1
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +71 -53
- package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +19 -0
- package/lib/components/settings/wrappers/component/SelectWithTitle.js +136 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.d.ts +10 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.js +111 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +233 -97
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +71 -54
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +63 -23
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +13 -2
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +42 -28
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +3 -3
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +52 -32
- package/lib/components/subModel/AddSubModelButton.d.ts +7 -0
- package/lib/components/subModel/AddSubModelButton.js +78 -8
- package/lib/components/subModel/LazyDropdown.js +14 -15
- package/lib/components/subModel/utils.d.ts +1 -1
- package/lib/components/subModel/utils.js +21 -11
- package/lib/components/variables/VariableInput.js +26 -6
- package/lib/components/variables/VariableTag.js +43 -2
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/components/variables/utils.js +4 -2
- package/lib/data-source/index.d.ts +23 -4
- package/lib/data-source/index.js +135 -14
- package/lib/data-source/jioToJoiSchema.js +1 -0
- package/lib/emitter.d.ts +6 -0
- package/lib/emitter.js +12 -0
- package/lib/executor/FlowExecutor.d.ts +6 -6
- package/lib/executor/FlowExecutor.js +302 -99
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
- package/lib/flowContext.d.ts +105 -6
- package/lib/flowContext.js +447 -139
- package/lib/flowEngine.d.ts +71 -1
- package/lib/flowEngine.js +319 -16
- package/lib/flowSettings.d.ts +4 -3
- package/lib/flowSettings.js +45 -21
- package/lib/hooks/useApplyAutoFlows.d.ts +1 -0
- package/lib/hooks/useApplyAutoFlows.js +3 -2
- package/lib/index.d.ts +14 -3
- package/lib/index.js +54 -7
- package/lib/locale/de-DE.json +62 -0
- package/lib/locale/en-US.json +57 -45
- package/lib/locale/es-ES.json +62 -0
- package/lib/locale/fr-FR.json +62 -0
- package/lib/locale/hu-HU.json +62 -0
- package/lib/locale/id-ID.json +62 -0
- package/lib/locale/index.d.ts +114 -90
- package/lib/locale/it-IT.json +62 -0
- package/lib/locale/ja-JP.json +62 -0
- package/lib/locale/ko-KR.json +62 -0
- package/lib/locale/nl-NL.json +62 -0
- package/lib/locale/pt-BR.json +62 -0
- package/lib/locale/ru-RU.json +62 -0
- package/lib/locale/tr-TR.json +62 -0
- package/lib/locale/uk-UA.json +62 -0
- package/lib/locale/vi-VN.json +62 -0
- package/lib/locale/zh-CN.json +58 -46
- package/lib/locale/zh-TW.json +62 -0
- package/lib/models/CollectionFieldModel.d.ts +7 -2
- package/lib/models/CollectionFieldModel.js +63 -16
- package/lib/models/flowModel.d.ts +76 -32
- package/lib/models/flowModel.js +300 -112
- package/lib/models/forkFlowModel.d.ts +8 -4
- package/lib/models/forkFlowModel.js +38 -8
- package/lib/provider.d.ts +3 -1
- package/lib/provider.js +14 -11
- package/lib/reactive/index.d.ts +10 -0
- package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → reactive/index.js} +14 -15
- package/lib/reactive/observer.d.ts +19 -0
- package/lib/reactive/observer.js +109 -0
- package/lib/resources/baseRecordResource.d.ts +6 -0
- package/lib/resources/baseRecordResource.js +38 -3
- package/lib/resources/multiRecordResource.d.ts +5 -2
- package/lib/resources/multiRecordResource.js +26 -10
- package/lib/resources/singleRecordResource.js +8 -3
- package/lib/resources/sqlResource.d.ts +5 -3
- package/lib/resources/sqlResource.js +30 -28
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +37 -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/JSEditableFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -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 +34 -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 +879 -0
- package/lib/runjs-context/contributions.d.ts +33 -0
- package/lib/runjs-context/contributions.js +88 -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 +88 -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 +24 -3
- package/lib/runjs-context/snippets/index.js +183 -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-antd-icons.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
- 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/runjsLibs.d.ts +28 -0
- package/lib/runjsLibs.js +532 -0
- package/lib/scheduler/ModelOperationScheduler.d.ts +53 -0
- package/lib/scheduler/ModelOperationScheduler.js +262 -0
- package/lib/types.d.ts +66 -7
- package/lib/types.js +4 -3
- package/lib/utils/associationObjectVariable.d.ts +32 -0
- package/lib/utils/associationObjectVariable.js +157 -0
- package/lib/utils/createCollectionContextMeta.d.ts +1 -1
- package/lib/utils/createCollectionContextMeta.js +9 -4
- package/lib/utils/createEphemeralContext.d.ts +13 -0
- package/lib/utils/createEphemeralContext.js +140 -0
- package/lib/utils/flows.d.ts +10 -0
- package/lib/{runjs-context/snippets/global/console-log-ctx.snippet.js → utils/flows.js} +21 -14
- package/lib/utils/index.d.ts +9 -3
- package/lib/utils/index.js +30 -2
- package/lib/utils/jsxTransform.d.ts +15 -0
- package/lib/utils/jsxTransform.js +68 -0
- package/lib/utils/params-resolvers.js +19 -12
- package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
- package/lib/utils/parsePathnameToViewParams.js +41 -5
- package/lib/utils/pruneFilter.d.ts +21 -0
- package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
- package/lib/utils/resolveModuleUrl.d.ts +58 -0
- package/lib/utils/resolveModuleUrl.js +65 -0
- package/lib/utils/runjsModuleLoader.d.ts +58 -0
- package/lib/utils/runjsModuleLoader.js +422 -0
- package/lib/utils/runjsTemplateCompat.d.ts +35 -0
- package/lib/utils/runjsTemplateCompat.js +743 -0
- package/lib/utils/safeGlobals.d.ts +6 -8
- package/lib/utils/safeGlobals.js +169 -14
- package/lib/utils/schema-utils.d.ts +6 -0
- package/lib/utils/schema-utils.js +71 -6
- package/lib/utils/serverContextParams.d.ts +4 -0
- package/lib/utils/serverContextParams.js +2 -0
- package/lib/utils/translation.d.ts +4 -1
- package/lib/utils/translation.js +6 -2
- package/lib/utils/variablesParams.d.ts +22 -5
- package/lib/utils/variablesParams.js +141 -61
- package/lib/views/DialogComponent.js +1 -5
- package/lib/views/DrawerComponent.js +18 -9
- package/lib/views/PageComponent.js +5 -5
- package/lib/views/ViewNavigation.d.ts +11 -15
- package/lib/views/ViewNavigation.js +37 -19
- package/lib/views/createViewMeta.d.ts +27 -5
- package/lib/views/createViewMeta.js +338 -72
- package/lib/views/index.d.ts +1 -1
- package/lib/views/index.js +4 -0
- package/lib/views/useDialog.d.ts +10 -9
- package/lib/views/useDialog.js +46 -34
- package/lib/views/useDrawer.d.ts +10 -9
- package/lib/views/useDrawer.js +74 -48
- package/lib/views/usePage.d.ts +14 -9
- package/lib/views/usePage.js +82 -33
- package/lib/views/usePopover.js +4 -1
- package/lib/views/viewEvents.d.ts +17 -0
- package/lib/views/viewEvents.js +90 -0
- package/package.json +6 -3
- package/src/BlockScopedFlowEngine.ts +85 -0
- package/src/FlowContextProvider.tsx +4 -2
- package/src/JSRunner.ts +39 -1
- package/src/ViewScopedFlowEngine.ts +21 -1
- package/src/__tests__/JSRunner.test.ts +125 -52
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/createViewMeta.popup.test.ts +203 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContext.test.ts +160 -0
- package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
- package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
- package/src/__tests__/flowEngine.destroyModel.test.ts +74 -0
- package/src/__tests__/flowEngine.moveModel.test.ts +43 -0
- package/src/__tests__/flowEngine.removeModel.test.ts +72 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +31 -2
- package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
- package/src/__tests__/flowSettings.open.test.tsx +71 -15
- package/src/__tests__/flowSettings.test.ts +2 -0
- package/src/__tests__/globalFlowRegistry.test.ts +1 -1
- package/src/__tests__/modelOperationScheduler.test.ts +346 -0
- package/src/__tests__/objectVariable.test.ts +464 -0
- package/src/__tests__/provider.test.tsx +0 -5
- package/src/__tests__/runjsContext.test.ts +219 -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__/runjsExternalLibs.test.ts +242 -0
- package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
- package/src/__tests__/runjsLocales.test.ts +39 -0
- package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
- package/src/__tests__/runjsSnippets.test.ts +140 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +101 -3
- package/src/acl/Acl.tsx +85 -31
- package/src/acl/__tests__/Acl.test.tsx +43 -1
- package/src/components/DynamicFlowsEditor.tsx +0 -10
- package/src/components/FieldModelRenderer.tsx +22 -9
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +20 -2
- package/src/components/FlowModelRenderer.tsx +52 -84
- package/src/components/FormItem.tsx +8 -1
- package/src/components/MobilePopup.style.ts +220 -0
- package/src/components/MobilePopup.tsx +86 -0
- package/src/components/__tests__/FlowModelRenderer.test.tsx +89 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
- package/src/components/__tests__/gridDragPlanner.test.ts +141 -1
- package/src/components/common/withFlowDesignMode.tsx +5 -5
- package/src/components/dnd/gridDragPlanner.ts +60 -0
- package/src/components/index.ts +1 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +34 -17
- package/src/components/settings/wrappers/component/SelectWithTitle.tsx +110 -0
- package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +83 -0
- package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +272 -125
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +34 -18
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +56 -18
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +1 -2
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -1
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +624 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +47 -35
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +1 -1
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +64 -42
- package/src/components/subModel/AddSubModelButton.tsx +104 -9
- package/src/components/subModel/LazyDropdown.tsx +14 -14
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +168 -7
- package/src/components/subModel/__tests__/utils.test.ts +12 -12
- package/src/components/subModel/utils.ts +25 -6
- package/src/components/variables/VariableInput.tsx +32 -6
- package/src/components/variables/VariableTag.tsx +54 -2
- package/src/components/variables/types.ts +2 -0
- package/src/components/variables/utils.ts +7 -3
- package/src/data-source/index.ts +143 -12
- package/src/data-source/jioToJoiSchema.ts +1 -0
- package/src/emitter.ts +14 -0
- package/src/executor/FlowExecutor.ts +383 -119
- package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
- package/src/executor/__tests__/flowExecutor.test.ts +217 -5
- package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
- package/src/flowContext.ts +646 -158
- package/src/flowEngine.ts +385 -14
- package/src/flowSettings.ts +59 -30
- package/src/hooks/useApplyAutoFlows.ts +5 -3
- package/src/index.ts +26 -3
- package/src/locale/de-DE.json +62 -0
- package/src/locale/en-US.json +57 -45
- package/src/locale/es-ES.json +62 -0
- package/src/locale/fr-FR.json +62 -0
- package/src/locale/hu-HU.json +62 -0
- package/src/locale/id-ID.json +62 -0
- package/src/locale/it-IT.json +62 -0
- package/src/locale/ja-JP.json +62 -0
- package/src/locale/ko-KR.json +62 -0
- package/src/locale/nl-NL.json +62 -0
- package/src/locale/pt-BR.json +62 -0
- package/src/locale/ru-RU.json +62 -0
- package/src/locale/tr-TR.json +62 -0
- package/src/locale/uk-UA.json +62 -0
- package/src/locale/vi-VN.json +62 -0
- package/src/locale/zh-CN.json +58 -46
- package/src/locale/zh-TW.json +62 -0
- package/src/models/CollectionFieldModel.tsx +82 -18
- package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
- package/src/models/__tests__/dispatchEvent.when.test.ts +356 -0
- package/src/models/__tests__/flowEngine.resolveUse.test.ts +170 -0
- package/src/models/__tests__/flowModel.clone.test.ts +416 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
- package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
- package/src/models/__tests__/flowModel.test.ts +296 -119
- package/src/models/__tests__/forkFlowModel.test.ts +40 -7
- package/src/models/flowModel.tsx +426 -148
- package/src/models/forkFlowModel.ts +48 -8
- package/src/provider.tsx +18 -14
- package/src/reactive/__tests__/observer.test.tsx +211 -0
- package/src/reactive/index.ts +11 -0
- package/src/reactive/observer.tsx +101 -0
- package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
- package/src/resources/__tests__/sqlResource.test.ts +60 -0
- package/src/resources/baseRecordResource.ts +46 -3
- package/src/resources/multiRecordResource.ts +28 -12
- package/src/resources/singleRecordResource.ts +9 -3
- package/src/resources/sqlResource.ts +33 -32
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +38 -21
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +50 -34
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
- package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +35 -21
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
- package/src/runjs-context/contexts/base.ts +871 -0
- package/src/runjs-context/contributions.ts +88 -0
- package/src/runjs-context/helpers.ts +32 -30
- package/src/runjs-context/registry.ts +16 -47
- package/src/runjs-context/setup.ts +57 -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 +212 -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-antd-icons.snippet.ts +46 -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/runjsLibs.ts +622 -0
- package/src/scheduler/ModelOperationScheduler.ts +306 -0
- package/src/types.ts +86 -5
- package/src/utils/__tests__/createCollectionContextMeta.test.ts +51 -0
- package/src/utils/__tests__/flows.test.ts +65 -0
- package/src/utils/__tests__/jsxTransform.test.ts +38 -0
- package/src/utils/__tests__/params-resolvers.test.ts +40 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
- package/src/utils/__tests__/pruneFilter.test.ts +38 -0
- package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
- package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
- package/src/utils/__tests__/safeGlobals.test.ts +79 -2
- package/src/utils/__tests__/utils.test.ts +114 -15
- package/src/utils/__tests__/variablesParams.test.ts +120 -0
- package/src/utils/associationObjectVariable.ts +180 -0
- package/src/utils/createCollectionContextMeta.ts +9 -3
- package/src/utils/createEphemeralContext.ts +142 -0
- package/src/utils/flows.ts +23 -0
- package/src/utils/index.ts +17 -3
- package/src/utils/jsxTransform.ts +39 -0
- package/src/utils/params-resolvers.ts +25 -11
- package/src/utils/parsePathnameToViewParams.ts +50 -6
- package/src/utils/pruneFilter.ts +41 -0
- package/src/utils/resolveModuleUrl.ts +91 -0
- package/src/utils/runjsModuleLoader.ts +553 -0
- package/src/utils/runjsTemplateCompat.ts +828 -0
- package/src/utils/safeGlobals.ts +181 -15
- package/src/utils/schema-utils.ts +81 -3
- package/src/utils/serverContextParams.ts +6 -0
- package/src/utils/translation.ts +7 -2
- package/src/utils/variablesParams.ts +164 -72
- package/src/views/DialogComponent.tsx +1 -4
- package/src/views/DrawerComponent.tsx +19 -7
- package/src/views/PageComponent.tsx +3 -5
- package/src/views/ViewNavigation.ts +49 -43
- package/src/views/__tests__/FlowView.usePage.test.tsx +186 -0
- package/src/views/__tests__/ViewNavigation.test.ts +54 -34
- package/src/views/__tests__/useDialog.closeDestroy.test.tsx +159 -0
- package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
- package/src/views/createViewMeta.ts +402 -73
- package/src/views/index.tsx +1 -1
- package/src/views/useDialog.tsx +52 -31
- package/src/views/useDrawer.tsx +99 -55
- package/src/views/usePage.tsx +101 -33
- package/src/views/usePopover.tsx +4 -1
- package/src/views/viewEvents.ts +55 -0
- 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/console-log-ctx.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
- 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/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-mount.snippet.js +0 -46
- 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/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
|
@@ -12,6 +12,7 @@ import { FlowForkModelContext, FlowModelContext } from '../flowContext';
|
|
|
12
12
|
import type { IModelComponentProps } from '../types';
|
|
13
13
|
import { FlowModel } from './flowModel';
|
|
14
14
|
import { FlowEngine } from '../flowEngine';
|
|
15
|
+
import { uid } from 'uid/secure';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* ForkFlowModel 作为 FlowModel 的独立实例:
|
|
@@ -38,7 +39,7 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
|
|
|
38
39
|
private disposed = false;
|
|
39
40
|
|
|
40
41
|
/** fork 在 master.forks 中的索引 */
|
|
41
|
-
public readonly forkId:
|
|
42
|
+
public readonly forkId: string;
|
|
42
43
|
|
|
43
44
|
/** 需要与 master 共享的属性列表 */
|
|
44
45
|
private static readonly SHARED_PROPERTIES = ['stepParams', 'sortIndex'];
|
|
@@ -67,12 +68,12 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
|
|
|
67
68
|
// 不需要定义自己的属性了,现在是SHARED_PROPERTIES中指定的少数几个属性,所有属性设置时会自动添加自己的fork内的独有属性
|
|
68
69
|
#flowContext: FlowModelContext;
|
|
69
70
|
|
|
70
|
-
constructor(master: TMaster, initialProps: IModelComponentProps = {}, forkId
|
|
71
|
+
constructor(master: TMaster, initialProps: IModelComponentProps = {}, forkId?: string) {
|
|
71
72
|
void this.localProperties; // 避免 IDE 提示 unused
|
|
72
73
|
this.master = master;
|
|
73
74
|
this.uid = master.uid;
|
|
74
75
|
this.localProps = { ...initialProps };
|
|
75
|
-
this.forkId = forkId;
|
|
76
|
+
this.forkId = forkId || uid();
|
|
76
77
|
this.hidden = this.master.hidden;
|
|
77
78
|
|
|
78
79
|
define(this, {
|
|
@@ -206,6 +207,13 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
|
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
209
|
|
|
210
|
+
/**
|
|
211
|
+
* 清理局部 props,仅影响当前 fork
|
|
212
|
+
*/
|
|
213
|
+
clearProps() {
|
|
214
|
+
return (this.localProps = {});
|
|
215
|
+
}
|
|
216
|
+
|
|
209
217
|
/**
|
|
210
218
|
* render 依旧使用 master 的方法,但合并后的 props 需要透传
|
|
211
219
|
*/
|
|
@@ -224,10 +232,10 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
|
|
|
224
232
|
}
|
|
225
233
|
|
|
226
234
|
/**
|
|
227
|
-
*
|
|
235
|
+
* 事件缓存的作用域标识(fork 专用)。
|
|
228
236
|
*/
|
|
229
|
-
public
|
|
230
|
-
return String(this.forkId)
|
|
237
|
+
public getFlowCacheScope(eventName: string): string {
|
|
238
|
+
return `${String(eventName)}:${String(this.forkId)}`;
|
|
231
239
|
}
|
|
232
240
|
|
|
233
241
|
// onUnmount() {
|
|
@@ -250,9 +258,41 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
|
|
|
250
258
|
dispose() {
|
|
251
259
|
if (this.disposed) return;
|
|
252
260
|
this.disposed = true;
|
|
261
|
+
// 统一按事件缓存命名规则清理当前 fork 的所有缓存项(覆盖所有事件)
|
|
262
|
+
try {
|
|
263
|
+
const cache = this.flowEngine?.applyFlowCache;
|
|
264
|
+
if (cache && cache.size > 0) {
|
|
265
|
+
const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
|
|
266
|
+
const forkIdColon = `:${this.forkId}:`;
|
|
267
|
+
const forkIdHyphen = `-${this.forkId}-`;
|
|
268
|
+
|
|
269
|
+
for (const key of cache.keys()) {
|
|
270
|
+
// 事件缓存统一以 event: 或 event- 开头
|
|
271
|
+
const isEventCache = key.startsWith('event:') || key.startsWith('event-');
|
|
272
|
+
if (!isEventCache) continue;
|
|
273
|
+
|
|
274
|
+
// 仅删除当前 fork + 当前 uid 的键
|
|
275
|
+
const endMatches = uidSuffixes.some((s) => key.endsWith(s));
|
|
276
|
+
if (!endMatches) continue;
|
|
277
|
+
|
|
278
|
+
// 限定在去除 uid 后缀的范围内匹配 forkId 片段,避免误伤
|
|
279
|
+
let trimmed = key;
|
|
280
|
+
for (const suf of uidSuffixes) {
|
|
281
|
+
if (trimmed.endsWith(suf)) {
|
|
282
|
+
trimmed = trimmed.slice(0, -suf.length);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (trimmed.includes(forkIdColon) || trimmed.includes(forkIdHyphen)) {
|
|
287
|
+
cache.delete(key);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
// 忽略清理阶段异常,避免影响后续释放
|
|
293
|
+
}
|
|
294
|
+
|
|
253
295
|
if (this.master && (this.master as any).forks) {
|
|
254
|
-
const forkCacheKey = FlowEngine.generateApplyFlowCacheKey(`${this.forkId}`, 'all', this.uid);
|
|
255
|
-
this.flowEngine.applyFlowCache.delete(forkCacheKey);
|
|
256
296
|
(this.master as any).forks.delete(this as any);
|
|
257
297
|
}
|
|
258
298
|
// 从 master 的 forkCache 中移除自己
|
package/src/provider.tsx
CHANGED
|
@@ -22,7 +22,7 @@ interface FlowEngineProviderProps {
|
|
|
22
22
|
|
|
23
23
|
const FlowEngineReactContext = createContext<FlowEngine | null>(null);
|
|
24
24
|
|
|
25
|
-
export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = (props) => {
|
|
25
|
+
export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = React.memo((props) => {
|
|
26
26
|
const { engine, children } = props;
|
|
27
27
|
if (!engine) {
|
|
28
28
|
throw new Error('FlowEngineProvider must be supplied with an engine.');
|
|
@@ -32,7 +32,9 @@ export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = (props) =>
|
|
|
32
32
|
<FlowContextProvider context={engine.context}>{children}</FlowContextProvider>
|
|
33
33
|
</FlowEngineReactContext.Provider>
|
|
34
34
|
);
|
|
35
|
-
};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
FlowEngineProvider.displayName = 'FlowEngineProvider';
|
|
36
38
|
|
|
37
39
|
export const FlowEngineGlobalsContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
38
40
|
const { modal, message, notification } = App.useApp();
|
|
@@ -56,41 +58,43 @@ export const FlowEngineGlobalsContextProvider: React.FC<{ children: React.ReactN
|
|
|
56
58
|
cache: false,
|
|
57
59
|
get: (ctx) => new FlowViewer(ctx, { drawer, embed, popover, dialog }),
|
|
58
60
|
});
|
|
59
|
-
// 将 themeToken 定义为 observable, 使组件能够响应主题的变更
|
|
60
|
-
engine.context.defineProperty('themeToken', {
|
|
61
|
-
get: () => token,
|
|
62
|
-
observable: true,
|
|
63
|
-
cache: true,
|
|
64
|
-
});
|
|
65
61
|
for (const item of Object.entries(context)) {
|
|
66
62
|
const [key, value] = item;
|
|
67
63
|
if (value) {
|
|
68
64
|
engine.context.defineProperty(key, { value });
|
|
69
65
|
}
|
|
70
66
|
}
|
|
67
|
+
// 将 themeToken 定义为 observable, 使组件能够响应主题的变更
|
|
68
|
+
// NOTE: 必须在 antdConfig 写入后再更新 themeToken;否则会读取到旧 antdConfig 的值。
|
|
69
|
+
engine.context.defineProperty('themeToken', {
|
|
70
|
+
get: () => token,
|
|
71
|
+
observable: true,
|
|
72
|
+
cache: true,
|
|
73
|
+
});
|
|
71
74
|
engine.reactView.refresh();
|
|
72
75
|
}, [engine, drawer, modal, message, notification, config, popover, token, dialog, embed]);
|
|
73
76
|
|
|
74
77
|
return (
|
|
75
|
-
|
|
78
|
+
<ConfigProvider {...config} locale={engine.context.locales?.antd} popupMatchSelectWidth={false}>
|
|
76
79
|
{children}
|
|
77
80
|
{contextHolder as any}
|
|
78
81
|
{popoverContextHolder as any}
|
|
79
82
|
{pageContextHolder as any}
|
|
80
83
|
{dialogContextHolder as any}
|
|
81
84
|
{/* The modal context is provided by App.useApp() */}
|
|
82
|
-
|
|
85
|
+
</ConfigProvider>
|
|
83
86
|
);
|
|
84
87
|
};
|
|
85
|
-
|
|
86
|
-
export const useFlowEngine = (): FlowEngine => {
|
|
88
|
+
// 不 throw Error 怎么处理?
|
|
89
|
+
export const useFlowEngine = ({ throwError = true } = {}): FlowEngine => {
|
|
87
90
|
const context = useContext(FlowEngineReactContext);
|
|
88
|
-
if (!context) {
|
|
91
|
+
if (!context && throwError) {
|
|
89
92
|
// This error should ideally not be hit if FlowEngineProvider is used correctly at the root
|
|
90
93
|
// and always supplied with an engine.
|
|
91
|
-
|
|
94
|
+
console.warn(
|
|
92
95
|
'useFlowEngine must be used within a FlowEngineProvider, and FlowEngineProvider must be supplied with an engine.',
|
|
93
96
|
);
|
|
97
|
+
return;
|
|
94
98
|
}
|
|
95
99
|
return context;
|
|
96
100
|
};
|
|
@@ -0,0 +1,211 @@
|
|
|
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 React from 'react';
|
|
11
|
+
import { render, screen, act } from '@testing-library/react';
|
|
12
|
+
import { observer } from '../observer';
|
|
13
|
+
import { useFlowContext } from '../../FlowContextProvider';
|
|
14
|
+
import { observable } from '@formily/reactive';
|
|
15
|
+
import { vi } from 'vitest';
|
|
16
|
+
import { sleep } from '@nocobase/test/client';
|
|
17
|
+
|
|
18
|
+
// Mock useFlowContext
|
|
19
|
+
vi.mock('../../FlowContextProvider', async () => {
|
|
20
|
+
const actual = await vi.importActual('../../FlowContextProvider');
|
|
21
|
+
return {
|
|
22
|
+
...actual,
|
|
23
|
+
useFlowContext: vi.fn(),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('observer', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
(useFlowContext as any).mockReturnValue({});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should render component', () => {
|
|
37
|
+
const Component = observer(() => <div>Hello World</div>);
|
|
38
|
+
render(<Component />);
|
|
39
|
+
expect(screen.getByText('Hello World')).toBeInTheDocument();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should update when observable changes', async () => {
|
|
43
|
+
const model = observable({ count: 0 });
|
|
44
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
45
|
+
render(<Component />);
|
|
46
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
47
|
+
|
|
48
|
+
act(() => {
|
|
49
|
+
model.count++;
|
|
50
|
+
});
|
|
51
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should delay update when pageActive is false', async () => {
|
|
55
|
+
const model = observable({ count: 0 });
|
|
56
|
+
const pageActive = observable.ref(false);
|
|
57
|
+
const tabActive = observable.ref(true);
|
|
58
|
+
|
|
59
|
+
const context = {
|
|
60
|
+
pageActive: pageActive,
|
|
61
|
+
tabActive: tabActive,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
(useFlowContext as any).mockReturnValue(context);
|
|
65
|
+
|
|
66
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
67
|
+
|
|
68
|
+
render(<Component />);
|
|
69
|
+
|
|
70
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
71
|
+
|
|
72
|
+
// Update model, but pageActive is false
|
|
73
|
+
act(() => {
|
|
74
|
+
model.count++;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await sleep(30);
|
|
78
|
+
|
|
79
|
+
// Should not update yet
|
|
80
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
81
|
+
expect(screen.queryByText('Count: 1')).not.toBeInTheDocument();
|
|
82
|
+
|
|
83
|
+
// Now make pageActive true
|
|
84
|
+
act(() => {
|
|
85
|
+
pageActive.value = true;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await sleep(30);
|
|
89
|
+
|
|
90
|
+
// Should update now
|
|
91
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should delay update when tabActive is false', async () => {
|
|
95
|
+
const model = observable({ count: 0 });
|
|
96
|
+
const pageActive = observable.ref(true);
|
|
97
|
+
const tabActive = observable.ref(false);
|
|
98
|
+
|
|
99
|
+
const context = {
|
|
100
|
+
pageActive: pageActive,
|
|
101
|
+
tabActive: tabActive,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
(useFlowContext as any).mockReturnValue(context);
|
|
105
|
+
|
|
106
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
107
|
+
|
|
108
|
+
render(<Component />);
|
|
109
|
+
|
|
110
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
111
|
+
|
|
112
|
+
// Update model, but tabActive is false
|
|
113
|
+
act(() => {
|
|
114
|
+
model.count++;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
await sleep(30);
|
|
118
|
+
|
|
119
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
120
|
+
expect(screen.queryByText('Count: 1')).not.toBeInTheDocument();
|
|
121
|
+
|
|
122
|
+
// Now make tabActive true
|
|
123
|
+
act(() => {
|
|
124
|
+
tabActive.value = true;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await sleep(30);
|
|
128
|
+
|
|
129
|
+
// Should update now
|
|
130
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should update immediately when pageActive and tabActive are true', async () => {
|
|
134
|
+
const model = observable({ count: 0 });
|
|
135
|
+
const pageActive = observable.ref(true);
|
|
136
|
+
const tabActive = observable.ref(true);
|
|
137
|
+
|
|
138
|
+
const context = {
|
|
139
|
+
pageActive: pageActive,
|
|
140
|
+
tabActive: tabActive,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
(useFlowContext as any).mockReturnValue(context);
|
|
144
|
+
|
|
145
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
146
|
+
|
|
147
|
+
render(<Component />);
|
|
148
|
+
|
|
149
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
150
|
+
|
|
151
|
+
act(() => {
|
|
152
|
+
model.count++;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should handle undefined tabActive as true (backward compatibility or default)', async () => {
|
|
159
|
+
const model = observable({ count: 0 });
|
|
160
|
+
const pageActive = observable.ref(true);
|
|
161
|
+
// tabActive is undefined in context
|
|
162
|
+
|
|
163
|
+
const context = {
|
|
164
|
+
pageActive: pageActive,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
(useFlowContext as any).mockReturnValue(context);
|
|
168
|
+
|
|
169
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
170
|
+
|
|
171
|
+
render(<Component />);
|
|
172
|
+
|
|
173
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
174
|
+
|
|
175
|
+
act(() => {
|
|
176
|
+
model.count++;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await sleep(30);
|
|
180
|
+
|
|
181
|
+
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should respect view inputArgs for initial check', async () => {
|
|
185
|
+
const model = observable({ count: 0 });
|
|
186
|
+
|
|
187
|
+
const context = {
|
|
188
|
+
view: {
|
|
189
|
+
inputArgs: { pageActive: false },
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
(useFlowContext as any).mockReturnValue(context);
|
|
194
|
+
|
|
195
|
+
const Component = observer(() => <div>Count: {model.count}</div>);
|
|
196
|
+
|
|
197
|
+
render(<Component />);
|
|
198
|
+
|
|
199
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
200
|
+
|
|
201
|
+
act(() => {
|
|
202
|
+
model.count++;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
await sleep(30);
|
|
206
|
+
|
|
207
|
+
// Should NOT update because pageActive is false (from view.inputArgs)
|
|
208
|
+
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
209
|
+
expect(screen.queryByText('Count: 1')).not.toBeInTheDocument();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export * from '@formily/reactive';
|
|
11
|
+
export { observer, getPageActive } from './observer';
|
|
@@ -0,0 +1,101 @@
|
|
|
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 { observer as originalObserver, IObserverOptions, ReactFC } from '@formily/reactive-react';
|
|
11
|
+
import React, { useMemo, useEffect, useRef } from 'react';
|
|
12
|
+
import { useFlowContext } from '../FlowContextProvider';
|
|
13
|
+
import { autorun } from '@formily/reactive';
|
|
14
|
+
import { FlowEngineContext } from '..';
|
|
15
|
+
|
|
16
|
+
type ObserverComponentProps<P, Options extends IObserverOptions> = Options extends {
|
|
17
|
+
forwardRef: true;
|
|
18
|
+
}
|
|
19
|
+
? P & {
|
|
20
|
+
ref?: 'ref' extends keyof P ? P['ref'] : React.RefAttributes<any>;
|
|
21
|
+
}
|
|
22
|
+
: React.PropsWithoutRef<P>;
|
|
23
|
+
|
|
24
|
+
export const observer = <P, Options extends IObserverOptions = IObserverOptions>(
|
|
25
|
+
Component: ReactFC<P>,
|
|
26
|
+
options?: Options,
|
|
27
|
+
): React.MemoExoticComponent<ReactFC<ObserverComponentProps<P, Options>>> => {
|
|
28
|
+
const ComponentWithDefaultScheduler = React.memo((props: any) => {
|
|
29
|
+
const ctx = useFlowContext();
|
|
30
|
+
const ctxRef = useRef(ctx);
|
|
31
|
+
ctxRef.current = ctx;
|
|
32
|
+
|
|
33
|
+
// Store the pending disposer to avoid creating multiple listeners
|
|
34
|
+
const pendingDisposerRef = useRef<(() => void) | null>(null);
|
|
35
|
+
|
|
36
|
+
// Cleanup on unmount
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
return () => {
|
|
39
|
+
if (pendingDisposerRef.current) {
|
|
40
|
+
pendingDisposerRef.current();
|
|
41
|
+
pendingDisposerRef.current = null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const ObservedComponent = useMemo(
|
|
47
|
+
() =>
|
|
48
|
+
originalObserver(Component, {
|
|
49
|
+
scheduler(updater) {
|
|
50
|
+
const pageActive = getPageActive(ctxRef.current);
|
|
51
|
+
const tabActive = ctxRef.current?.tabActive?.value;
|
|
52
|
+
|
|
53
|
+
if (pageActive === false || tabActive === false) {
|
|
54
|
+
// Avoid stack overflow
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
// If there is already a pending updater, do nothing
|
|
57
|
+
if (pendingDisposerRef.current) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Delay the update until the page and tab become active
|
|
62
|
+
const disposer = autorun(() => {
|
|
63
|
+
if (
|
|
64
|
+
ctxRef.current?.pageActive?.value &&
|
|
65
|
+
(ctxRef.current?.tabActive?.value === true || ctxRef.current?.tabActive?.value === undefined)
|
|
66
|
+
) {
|
|
67
|
+
updater();
|
|
68
|
+
disposer?.();
|
|
69
|
+
pendingDisposerRef.current = null;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
pendingDisposerRef.current = disposer;
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// If we are updating immediately, clear any pending disposer
|
|
78
|
+
if (pendingDisposerRef.current) {
|
|
79
|
+
pendingDisposerRef.current();
|
|
80
|
+
pendingDisposerRef.current = null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
updater();
|
|
84
|
+
},
|
|
85
|
+
...options,
|
|
86
|
+
}),
|
|
87
|
+
[],
|
|
88
|
+
);
|
|
89
|
+
return <ObservedComponent {...props} />;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
ComponentWithDefaultScheduler.displayName = `ComponentWithDefaultScheduler`;
|
|
93
|
+
|
|
94
|
+
return ComponentWithDefaultScheduler as React.MemoExoticComponent<ReactFC<ObserverComponentProps<P, Options>>>;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export function getPageActive(context: FlowEngineContext): boolean | undefined {
|
|
98
|
+
return typeof context?.pageActive?.value === 'boolean'
|
|
99
|
+
? context?.pageActive?.value
|
|
100
|
+
: context?.view?.inputArgs.pageActive;
|
|
101
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
11
|
+
import { FlowEngine } from '../../flowEngine';
|
|
12
|
+
import { MultiRecordResource } from '../multiRecordResource';
|
|
13
|
+
|
|
14
|
+
function createMultiRecordResource() {
|
|
15
|
+
const engine = new FlowEngine();
|
|
16
|
+
return engine.createResource(MultiRecordResource);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('MultiRecordResource - refresh', () => {
|
|
20
|
+
it('should coalesce multiple refresh calls and settle all awaiters', async () => {
|
|
21
|
+
vi.useFakeTimers();
|
|
22
|
+
try {
|
|
23
|
+
const r = createMultiRecordResource();
|
|
24
|
+
const api = {
|
|
25
|
+
request: vi.fn().mockResolvedValue({
|
|
26
|
+
data: { data: [], meta: { count: 0, page: 1, pageSize: 20 } },
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
r.setAPIClient(api as any);
|
|
31
|
+
r.setResourceName('posts');
|
|
32
|
+
|
|
33
|
+
const p1 = r.refresh();
|
|
34
|
+
const p2 = r.refresh();
|
|
35
|
+
|
|
36
|
+
await vi.runAllTimersAsync();
|
|
37
|
+
await expect(p1).resolves.toBeUndefined();
|
|
38
|
+
await expect(p2).resolves.toBeUndefined();
|
|
39
|
+
expect(api.request).toHaveBeenCalledTimes(1);
|
|
40
|
+
} finally {
|
|
41
|
+
vi.useRealTimers();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
11
|
+
import { FlowEngine } from '../../flowEngine';
|
|
12
|
+
import { SQLResource } from '../sqlResource';
|
|
13
|
+
|
|
14
|
+
function createSQLResource() {
|
|
15
|
+
const engine = new FlowEngine();
|
|
16
|
+
return engine.createResource(SQLResource);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('SQLResource - refresh', () => {
|
|
20
|
+
it('should coalesce multiple refresh calls and settle all awaiters', async () => {
|
|
21
|
+
vi.useFakeTimers();
|
|
22
|
+
try {
|
|
23
|
+
const r = createSQLResource();
|
|
24
|
+
const run = vi.fn().mockResolvedValue({ data: { ok: 1 }, meta: { page: 1 } });
|
|
25
|
+
(r as any).run = run;
|
|
26
|
+
|
|
27
|
+
const p1 = r.refresh();
|
|
28
|
+
const p2 = r.refresh();
|
|
29
|
+
|
|
30
|
+
await vi.runAllTimersAsync();
|
|
31
|
+
await expect(p1).resolves.toBeUndefined();
|
|
32
|
+
await expect(p2).resolves.toBeUndefined();
|
|
33
|
+
expect(run).toHaveBeenCalledTimes(1);
|
|
34
|
+
} finally {
|
|
35
|
+
vi.useRealTimers();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should reject all awaiters on failure', async () => {
|
|
40
|
+
vi.useFakeTimers();
|
|
41
|
+
try {
|
|
42
|
+
const r = createSQLResource();
|
|
43
|
+
const run = vi.fn().mockRejectedValue(new Error('boom'));
|
|
44
|
+
(r as any).run = run;
|
|
45
|
+
|
|
46
|
+
const p1 = r.refresh();
|
|
47
|
+
const p2 = r.refresh();
|
|
48
|
+
|
|
49
|
+
// Attach handlers before timers run to avoid unhandled rejection warnings.
|
|
50
|
+
const e1 = expect(p1).rejects.toThrow('boom');
|
|
51
|
+
const e2 = expect(p2).rejects.toThrow('boom');
|
|
52
|
+
await vi.runAllTimersAsync();
|
|
53
|
+
await e1;
|
|
54
|
+
await e2;
|
|
55
|
+
expect(run).toHaveBeenCalledTimes(1);
|
|
56
|
+
} finally {
|
|
57
|
+
vi.useRealTimers();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -12,6 +12,7 @@ import _ from 'lodash';
|
|
|
12
12
|
import { APIResource } from './apiResource';
|
|
13
13
|
import { FilterItem } from './filterItem';
|
|
14
14
|
import { ResourceError } from './flowResource';
|
|
15
|
+
import { DATA_SOURCE_DIRTY_EVENT } from '../views/viewEvents';
|
|
15
16
|
|
|
16
17
|
export abstract class BaseRecordResource<TData = any> extends APIResource<TData> {
|
|
17
18
|
protected resourceName: string;
|
|
@@ -95,6 +96,7 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
async runAction<TData = any, TMeta = any>(action: string, options: any) {
|
|
99
|
+
const { rawResponse, ...rest } = options;
|
|
98
100
|
const config = this.mergeRequestConfig(
|
|
99
101
|
_.omit(this.request, ['params', 'data', 'method']),
|
|
100
102
|
{
|
|
@@ -102,14 +104,18 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
102
104
|
url: this.buildURL(action),
|
|
103
105
|
},
|
|
104
106
|
this.runActionOptions?.[action],
|
|
105
|
-
|
|
107
|
+
rest,
|
|
106
108
|
);
|
|
107
109
|
if (['create', 'update', 'firstOrCreate', 'updateOrCreate'].includes(action)) {
|
|
108
110
|
config.params = config.params || {};
|
|
109
111
|
config.params.updateAssociationValues = this.getUpdateAssociationValues();
|
|
110
112
|
}
|
|
111
113
|
try {
|
|
112
|
-
const
|
|
114
|
+
const response = await this.api.request(config);
|
|
115
|
+
if (rawResponse) {
|
|
116
|
+
return response;
|
|
117
|
+
}
|
|
118
|
+
const { data } = response;
|
|
113
119
|
if (!data?.data) {
|
|
114
120
|
return data;
|
|
115
121
|
}
|
|
@@ -131,6 +137,36 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
131
137
|
return this.resourceName;
|
|
132
138
|
}
|
|
133
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Mark current resource as dirty on the root FlowEngine.
|
|
142
|
+
* Used to coordinate "refresh on active" across view stacks.
|
|
143
|
+
*/
|
|
144
|
+
protected markDataSourceDirty(resourceName?: string) {
|
|
145
|
+
const engine = this.context.engine;
|
|
146
|
+
if (!engine) return;
|
|
147
|
+
|
|
148
|
+
const dataSourceKey = this.getDataSourceKey() || 'main';
|
|
149
|
+
const resName = resourceName || this.getResourceName();
|
|
150
|
+
if (!resName) return;
|
|
151
|
+
|
|
152
|
+
const affectedResourceNames = new Set<string>([String(resName)]);
|
|
153
|
+
// Optional safety: association resources like "users.profile" may impact parent collection views.
|
|
154
|
+
if (typeof resName === 'string' && resName.includes('.')) {
|
|
155
|
+
affectedResourceNames.add(resName.split('.')[0]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const name of affectedResourceNames) {
|
|
159
|
+
engine.markDataSourceDirty(dataSourceKey, name);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Signal current view to re-evaluate dirty blocks (e.g., same-view sibling refresh).
|
|
163
|
+
// This is emitted on the *current* engine emitter (view-scoped) so it won't affect other views.
|
|
164
|
+
engine.emitter?.emit?.(DATA_SOURCE_DIRTY_EVENT, {
|
|
165
|
+
dataSourceKey,
|
|
166
|
+
resourceNames: Array.from(affectedResourceNames),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
134
170
|
setSourceId(sourceId: string | number) {
|
|
135
171
|
this.sourceId = sourceId;
|
|
136
172
|
return this;
|
|
@@ -227,8 +263,15 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
227
263
|
return this;
|
|
228
264
|
}
|
|
229
265
|
|
|
266
|
+
jsonStringify(value: any): string {
|
|
267
|
+
if (value !== null && typeof value === 'object') {
|
|
268
|
+
return JSON.stringify(value);
|
|
269
|
+
}
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
|
|
230
273
|
setFilterByTk(filterByTk: any) {
|
|
231
|
-
return this.addRequestParameter('filterByTk', filterByTk);
|
|
274
|
+
return this.addRequestParameter('filterByTk', this.jsonStringify(filterByTk));
|
|
232
275
|
}
|
|
233
276
|
|
|
234
277
|
getFilterByTk(): any {
|