@nocobase/flow-engine 2.0.0-alpha.4 → 2.0.0-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/BlockScopedFlowEngine.d.ts +23 -0
- package/lib/BlockScopedFlowEngine.js +90 -0
- package/lib/FlowContextProvider.d.ts +2 -2
- package/lib/FlowContextProvider.js +3 -3
- package/lib/FlowDefinition.d.ts +4 -2
- package/lib/JSRunner.js +3 -0
- package/lib/ViewScopedFlowEngine.d.ts +1 -1
- package/lib/ViewScopedFlowEngine.js +12 -0
- package/lib/acl/Acl.d.ts +1 -0
- package/lib/acl/Acl.js +11 -0
- package/lib/components/FieldModelRenderer.js +14 -6
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +7 -2
- package/lib/components/FlowModelRenderer.d.ts +3 -6
- package/lib/components/FlowModelRenderer.js +16 -47
- 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/index.d.ts +1 -0
- package/lib/components/index.js +3 -1
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +35 -6
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
- package/lib/components/variables/VariableInput.js +19 -5
- package/lib/components/variables/VariableTag.js +43 -2
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/data-source/index.d.ts +15 -4
- package/lib/data-source/index.js +42 -13
- package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
- package/lib/data-source/sortCollectionsByInherits.js +71 -0
- package/lib/emitter.d.ts +6 -0
- package/lib/emitter.js +12 -0
- package/lib/executor/FlowExecutor.d.ts +4 -5
- package/lib/executor/FlowExecutor.js +168 -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 +37 -5
- package/lib/flowContext.js +224 -87
- package/lib/flowEngine.d.ts +24 -1
- package/lib/flowEngine.js +81 -8
- package/lib/flowSettings.d.ts +2 -1
- package/lib/flowSettings.js +16 -8
- package/lib/hooks/useApplyAutoFlows.js +2 -1
- package/lib/index.d.ts +7 -1
- package/lib/index.js +32 -3
- package/lib/locale/en-US.json +4 -2
- package/lib/locale/index.d.ts +4 -0
- package/lib/locale/zh-CN.json +4 -2
- package/lib/models/CollectionFieldModel.d.ts +3 -0
- package/lib/models/CollectionFieldModel.js +52 -6
- package/lib/models/flowModel.d.ts +30 -29
- package/lib/models/flowModel.js +153 -100
- 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 +7 -5
- package/lib/resources/multiRecordResource.js +25 -1
- package/lib/resources/singleRecordResource.js +19 -1
- package/lib/resources/sqlResource.d.ts +1 -0
- package/lib/resources/sqlResource.js +20 -24
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
- package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
- package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
- package/lib/runjs-context/contexts/base.d.ts +9 -0
- package/lib/runjs-context/contexts/base.js +205 -0
- package/lib/runjs-context/helpers.d.ts +5 -2
- package/lib/runjs-context/helpers.js +36 -27
- package/lib/runjs-context/registry.d.ts +7 -4
- package/lib/runjs-context/registry.js +10 -42
- package/lib/runjs-context/setup.d.ts +9 -0
- package/lib/runjs-context/setup.js +82 -0
- package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
- package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
- package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
- package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/index.d.ts +14 -3
- package/lib/runjs-context/snippets/index.js +162 -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/scheduler/ModelOperationScheduler.d.ts +51 -0
- package/lib/scheduler/ModelOperationScheduler.js +262 -0
- package/lib/types.d.ts +28 -3
- package/lib/types.js +4 -3
- package/lib/utils/associationObjectVariable.d.ts +32 -0
- package/lib/utils/associationObjectVariable.js +157 -0
- package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
- package/lib/utils/buildSettingsViewInputArgs.js +75 -0
- package/lib/utils/createEphemeralContext.d.ts +13 -0
- package/lib/utils/createEphemeralContext.js +140 -0
- package/lib/utils/flows.d.ts +10 -0
- package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → utils/flows.js} +21 -15
- package/lib/utils/index.d.ts +7 -2
- package/lib/utils/index.js +21 -2
- package/lib/utils/jsxTransform.d.ts +15 -0
- package/lib/utils/jsxTransform.js +68 -0
- package/lib/utils/params-resolvers.js +3 -3
- package/lib/utils/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/safeGlobals.d.ts +5 -3
- package/lib/utils/safeGlobals.js +40 -0
- package/lib/utils/schema-utils.js +2 -2
- package/lib/utils/serverContextParams.d.ts +1 -0
- package/lib/utils/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 +132 -36
- package/lib/views/DrawerComponent.js +21 -2
- package/lib/views/PageComponent.js +2 -1
- package/lib/views/ViewNavigation.d.ts +3 -9
- package/lib/views/ViewNavigation.js +16 -2
- package/lib/views/createViewMeta.d.ts +29 -1
- package/lib/views/createViewMeta.js +338 -72
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +3 -0
- package/lib/views/useDialog.d.ts +9 -8
- package/lib/views/useDialog.js +19 -14
- package/lib/views/useDrawer.d.ts +9 -8
- package/lib/views/useDrawer.js +54 -35
- package/lib/views/usePage.d.ts +9 -8
- package/lib/views/usePage.js +20 -14
- package/package.json +6 -3
- package/src/BlockScopedFlowEngine.ts +86 -0
- package/src/FlowContextProvider.tsx +4 -2
- package/src/JSRunner.ts +3 -0
- package/src/ViewScopedFlowEngine.ts +15 -1
- package/src/__tests__/JSRunner.test.ts +62 -53
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/createViewMeta.popup.test.ts +132 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContext.test.ts +52 -0
- package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
- package/src/__tests__/flowSettings.open.test.tsx +2 -0
- 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__/runjsContext.test.ts +216 -35
- package/src/__tests__/runjsContextImplementations.test.ts +217 -0
- package/src/__tests__/runjsContextRuntime.test.ts +269 -0
- package/src/__tests__/runjsEdgeCases.test.ts +281 -0
- package/src/__tests__/runjsLocales.test.ts +36 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
- package/src/__tests__/runjsSnippets.test.ts +140 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
- package/src/acl/Acl.tsx +14 -0
- package/src/acl/__tests__/Acl.test.tsx +43 -0
- package/src/components/DynamicFlowsEditor.tsx +3 -4
- package/src/components/FieldModelRenderer.tsx +20 -7
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +6 -2
- package/src/components/FlowModelRenderer.tsx +33 -81
- 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__/flow-model-render-error-fallback.test.tsx +6 -6
- package/src/components/index.ts +1 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +39 -10
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +425 -0
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
- package/src/components/variables/VariableInput.tsx +25 -5
- package/src/components/variables/VariableTag.tsx +54 -2
- package/src/components/variables/types.ts +2 -0
- package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
- package/src/data-source/index.ts +42 -11
- package/src/data-source/sortCollectionsByInherits.ts +61 -0
- package/src/emitter.ts +14 -0
- package/src/executor/FlowExecutor.ts +213 -119
- package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
- package/src/executor/__tests__/flowExecutor.test.ts +151 -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 +303 -104
- package/src/flowEngine.ts +96 -6
- package/src/flowSettings.ts +12 -4
- package/src/hooks/useApplyAutoFlows.ts +3 -1
- package/src/index.ts +12 -1
- package/src/locale/en-US.json +4 -2
- package/src/locale/zh-CN.json +4 -2
- package/src/models/CollectionFieldModel.tsx +60 -8
- package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -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 +234 -111
- package/src/models/__tests__/forkFlowModel.test.ts +40 -7
- package/src/models/flowModel.tsx +197 -132
- package/src/models/forkFlowModel.ts +48 -8
- package/src/provider.tsx +10 -7
- package/src/resources/multiRecordResource.ts +28 -1
- package/src/resources/singleRecordResource.ts +19 -1
- package/src/resources/sqlResource.ts +20 -25
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
- package/src/runjs-context/contexts/base.ts +196 -0
- package/src/runjs-context/helpers.ts +32 -30
- package/src/runjs-context/registry.ts +16 -47
- package/src/runjs-context/setup.ts +51 -0
- package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
- package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
- package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
- package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/index.ts +178 -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/scheduler/ModelOperationScheduler.ts +304 -0
- package/src/types.ts +34 -0
- package/src/utils/__tests__/flows.test.ts +65 -0
- package/src/utils/__tests__/jsxTransform.test.ts +38 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
- package/src/utils/__tests__/pruneFilter.test.ts +38 -0
- package/src/utils/__tests__/safeGlobals.test.ts +22 -1
- package/src/utils/__tests__/variablesParams.test.ts +63 -0
- package/src/utils/associationObjectVariable.ts +180 -0
- package/src/utils/buildSettingsViewInputArgs.ts +72 -0
- package/src/utils/createEphemeralContext.ts +142 -0
- package/src/utils/flows.ts +23 -0
- package/src/utils/index.ts +11 -2
- package/src/utils/jsxTransform.ts +39 -0
- package/src/utils/params-resolvers.ts +2 -2
- package/src/utils/parsePathnameToViewParams.ts +50 -6
- package/src/utils/pruneFilter.ts +41 -0
- package/src/utils/safeGlobals.ts +49 -3
- package/src/utils/schema-utils.ts +1 -1
- package/src/utils/serverContextParams.ts +1 -0
- package/src/utils/translation.ts +7 -2
- package/src/utils/variablesParams.ts +156 -38
- package/src/views/DrawerComponent.tsx +21 -2
- package/src/views/PageComponent.tsx +1 -1
- package/src/views/ViewNavigation.ts +20 -12
- package/src/views/__tests__/ViewNavigation.test.ts +10 -0
- package/src/views/createViewMeta.ts +393 -70
- package/src/views/index.tsx +1 -0
- package/src/views/useDialog.tsx +24 -18
- package/src/views/useDrawer.tsx +74 -45
- package/src/views/usePage.tsx +26 -17
- 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/console-log-ctx.snippet.js +0 -41
- 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
|
@@ -0,0 +1,154 @@
|
|
|
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 { APIClient as SDKApiClient } from '@nocobase/sdk';
|
|
12
|
+
import { FlowEngine } from '../flowEngine';
|
|
13
|
+
import { createBlockScopedEngine } from '../BlockScopedFlowEngine';
|
|
14
|
+
import { FlowModel } from '../models';
|
|
15
|
+
|
|
16
|
+
describe('BlockScopedFlowEngine', () => {
|
|
17
|
+
it('shares global actions/events and model classes with parent', async () => {
|
|
18
|
+
const parent = new FlowEngine();
|
|
19
|
+
// 在运行时 host app 会注入 api,这里补一个最小 mock,避免偶发访问 ctx.auth 抛错
|
|
20
|
+
const api = new SDKApiClient({ storageType: 'memory' });
|
|
21
|
+
api.auth.role = 'guest';
|
|
22
|
+
api.auth.locale = 'en-US';
|
|
23
|
+
api.auth.token = 't';
|
|
24
|
+
parent.context.defineProperty('api', { value: api });
|
|
25
|
+
parent.registerActions({
|
|
26
|
+
ping: {
|
|
27
|
+
name: 'ping',
|
|
28
|
+
handler: () => 'pong',
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const child = createBlockScopedEngine(parent);
|
|
32
|
+
|
|
33
|
+
// child can read parent's action
|
|
34
|
+
expect(child.getAction('ping')).toBeDefined();
|
|
35
|
+
|
|
36
|
+
// registering via child should affect parent
|
|
37
|
+
child.registerActions({ pong: { name: 'pong', handler: () => 'ok' } });
|
|
38
|
+
expect(parent.getAction('pong')).toBeDefined();
|
|
39
|
+
|
|
40
|
+
// model class resolution is proxied
|
|
41
|
+
class TestModel extends FlowModel {}
|
|
42
|
+
parent.registerModels({ TestModel });
|
|
43
|
+
expect(child.getModelClass('TestModel')).toBeDefined();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('isolates model instances map and beforeRender cache across engines with identical model uid', async () => {
|
|
47
|
+
const parent = new FlowEngine();
|
|
48
|
+
// 提供最小 api mock,满足 ctx.auth 相关 getter
|
|
49
|
+
const api = new SDKApiClient({ storageType: 'memory' });
|
|
50
|
+
api.auth.role = 'guest';
|
|
51
|
+
api.auth.locale = 'en-US';
|
|
52
|
+
api.auth.token = 't';
|
|
53
|
+
parent.context.defineProperty('api', { value: api });
|
|
54
|
+
const child = createBlockScopedEngine(parent);
|
|
55
|
+
|
|
56
|
+
let count = 0;
|
|
57
|
+
class CounterModel extends FlowModel {}
|
|
58
|
+
CounterModel.registerFlow({
|
|
59
|
+
key: 'autoCounter',
|
|
60
|
+
steps: {
|
|
61
|
+
s1: {
|
|
62
|
+
handler: async () => {
|
|
63
|
+
count += 1;
|
|
64
|
+
return count;
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const uid = 'model-uid-cache';
|
|
71
|
+
const pm = parent.createModel<CounterModel>({ use: CounterModel, uid });
|
|
72
|
+
const cm = child.createModel<CounterModel>({ use: CounterModel, uid });
|
|
73
|
+
|
|
74
|
+
await pm.dispatchEvent('beforeRender');
|
|
75
|
+
expect(count).toBe(1);
|
|
76
|
+
|
|
77
|
+
// If cache was shared, the next call would hit cache and not increment.
|
|
78
|
+
await cm.dispatchEvent('beforeRender');
|
|
79
|
+
expect(count).toBe(2);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('stacks engines and repairs chain when unlinking a middle block-scoped engine', () => {
|
|
83
|
+
const root = new FlowEngine();
|
|
84
|
+
// 提供最小 api mock,满足 ctx.auth 相关 getter
|
|
85
|
+
const api = new SDKApiClient({ storageType: 'memory' });
|
|
86
|
+
api.auth.role = 'guest';
|
|
87
|
+
api.auth.locale = 'en-US';
|
|
88
|
+
api.auth.token = 't';
|
|
89
|
+
root.context.defineProperty('api', { value: api });
|
|
90
|
+
const c1 = createBlockScopedEngine(root);
|
|
91
|
+
const c2 = createBlockScopedEngine(root);
|
|
92
|
+
const c3 = createBlockScopedEngine(root);
|
|
93
|
+
|
|
94
|
+
// chain root -> c1 -> c2 -> c3
|
|
95
|
+
expect(root.nextEngine).toBeTruthy();
|
|
96
|
+
expect(root.nextEngine?.nextEngine).toBeTruthy();
|
|
97
|
+
expect(root.nextEngine?.nextEngine?.nextEngine).toBeTruthy();
|
|
98
|
+
|
|
99
|
+
// unlink middle (c2) should link c1 <-> c3 and keep the tail intact
|
|
100
|
+
c2.unlinkFromStack();
|
|
101
|
+
|
|
102
|
+
// root.nextEngine 指向的是被代理的本地 FlowEngine 实例,不与 c1 的 Proxy 引用相等
|
|
103
|
+
// 这里通过前后指针关系来校验链修复是否正确
|
|
104
|
+
const first = root.nextEngine;
|
|
105
|
+
const second = first?.nextEngine;
|
|
106
|
+
expect(first?.previousEngine).toBe(root);
|
|
107
|
+
expect(second?.previousEngine).toBe(first);
|
|
108
|
+
expect(second?.nextEngine).toBeUndefined();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('global model lookup traverses from top to root across stack', () => {
|
|
112
|
+
const root = new FlowEngine();
|
|
113
|
+
// 提供最小 api mock,满足 ctx.auth 相关 getter
|
|
114
|
+
const api = new SDKApiClient({ storageType: 'memory' });
|
|
115
|
+
api.auth.role = 'guest';
|
|
116
|
+
api.auth.locale = 'en-US';
|
|
117
|
+
api.auth.token = 't';
|
|
118
|
+
root.context.defineProperty('api', { value: api });
|
|
119
|
+
const c1 = createBlockScopedEngine(root);
|
|
120
|
+
const c2 = createBlockScopedEngine(root);
|
|
121
|
+
|
|
122
|
+
class TM extends FlowModel {}
|
|
123
|
+
const uid = 'same-uid-global-lookup';
|
|
124
|
+
const mRoot = root.createModel<TM>({ use: TM, uid });
|
|
125
|
+
const m1 = c1.createModel<TM>({ use: TM, uid });
|
|
126
|
+
const m2 = c2.createModel<TM>({ use: TM, uid });
|
|
127
|
+
|
|
128
|
+
// sanity: each scope returns its own when not global
|
|
129
|
+
expect(root.getModel(uid)).toBe(mRoot);
|
|
130
|
+
expect(c1.getModel(uid)).toBe(m1);
|
|
131
|
+
expect(c2.getModel(uid)).toBe(m2);
|
|
132
|
+
|
|
133
|
+
// global search from any engine hits the top-most engine's instance first
|
|
134
|
+
expect(root.getModel(uid, true)).toBe(m2);
|
|
135
|
+
expect(c1.getModel(uid, true)).toBe(m2);
|
|
136
|
+
expect(c2.getModel(uid, true)).toBe(m2);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('delegates saveModel to parent (concurrency gate sharing)', async () => {
|
|
140
|
+
const parent = new FlowEngine();
|
|
141
|
+
// 提供最小 api mock,满足 ctx.auth 相关 getter
|
|
142
|
+
const api = new SDKApiClient({ storageType: 'memory' });
|
|
143
|
+
api.auth.role = 'guest';
|
|
144
|
+
api.auth.locale = 'en-US';
|
|
145
|
+
api.auth.token = 't';
|
|
146
|
+
parent.context.defineProperty('api', { value: api });
|
|
147
|
+
const child = createBlockScopedEngine(parent);
|
|
148
|
+
const spy = vi.spyOn(parent, 'saveModel').mockResolvedValueOnce(true);
|
|
149
|
+
class T extends FlowModel {}
|
|
150
|
+
const m = child.createModel<T>({ use: T });
|
|
151
|
+
await child.saveModel(m);
|
|
152
|
+
expect(spy).toHaveBeenCalledOnce();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
11
|
+
import { FlowContext } from '../flowContext';
|
|
12
|
+
import { FlowEngine } from '../flowEngine';
|
|
13
|
+
import type { FlowView } from '../views/FlowView';
|
|
14
|
+
import { createPopupMeta } from '../views/createViewMeta';
|
|
15
|
+
|
|
16
|
+
describe('createViewMeta - popup variables', () => {
|
|
17
|
+
function makeCtx() {
|
|
18
|
+
const engine = new FlowEngine();
|
|
19
|
+
const ctx = new FlowContext();
|
|
20
|
+
ctx.defineProperty('engine', { value: engine });
|
|
21
|
+
// 简化 i18n:直接返回 key
|
|
22
|
+
ctx.defineProperty('t', { value: (s: string) => s });
|
|
23
|
+
return { engine, ctx };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
it('buildVariablesParams(record) uses anchor view instead of ctx.view', async () => {
|
|
27
|
+
const { engine, ctx } = makeCtx();
|
|
28
|
+
|
|
29
|
+
// 模拟锚定弹窗视图(被测试目标)
|
|
30
|
+
const anchorView: FlowView = {
|
|
31
|
+
type: 'embed',
|
|
32
|
+
inputArgs: {},
|
|
33
|
+
Header: null,
|
|
34
|
+
Footer: null,
|
|
35
|
+
close: () => void 0,
|
|
36
|
+
update: () => void 0,
|
|
37
|
+
navigation: {
|
|
38
|
+
viewStack: [
|
|
39
|
+
{
|
|
40
|
+
viewUid: 'popup-uid',
|
|
41
|
+
filterByTk: 111,
|
|
42
|
+
sourceId: 42,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
} as any,
|
|
46
|
+
} as any;
|
|
47
|
+
|
|
48
|
+
// ctx.view 指向另一个(例如设置弹窗)
|
|
49
|
+
ctx.defineProperty('view', {
|
|
50
|
+
value: {
|
|
51
|
+
type: 'dialog',
|
|
52
|
+
inputArgs: {},
|
|
53
|
+
navigation: {
|
|
54
|
+
viewStack: [
|
|
55
|
+
{
|
|
56
|
+
viewUid: 'settings-uid',
|
|
57
|
+
filterByTk: 9999,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// 为两个视图 uid 注入不同的 openView 配置,确保只取锚定视图
|
|
65
|
+
const popupModel = {
|
|
66
|
+
getStepParams: vi.fn((_fk: string, sk: string) =>
|
|
67
|
+
sk === 'openView'
|
|
68
|
+
? {
|
|
69
|
+
collectionName: 'posts',
|
|
70
|
+
dataSourceKey: 'main',
|
|
71
|
+
}
|
|
72
|
+
: undefined,
|
|
73
|
+
),
|
|
74
|
+
} as any;
|
|
75
|
+
const settingsModel = {
|
|
76
|
+
getStepParams: vi.fn((_fk: string, sk: string) =>
|
|
77
|
+
sk === 'openView'
|
|
78
|
+
? {
|
|
79
|
+
collectionName: 'comments',
|
|
80
|
+
dataSourceKey: 'main',
|
|
81
|
+
}
|
|
82
|
+
: undefined,
|
|
83
|
+
),
|
|
84
|
+
} as any;
|
|
85
|
+
|
|
86
|
+
const getModelSpy = vi.spyOn(engine as any, 'getModel');
|
|
87
|
+
getModelSpy.mockImplementation((uid: string) => (uid === 'popup-uid' ? popupModel : settingsModel));
|
|
88
|
+
|
|
89
|
+
const metaFactory = createPopupMeta(ctx, anchorView);
|
|
90
|
+
const meta = (await metaFactory())!;
|
|
91
|
+
|
|
92
|
+
// record 应来自锚定视图的 openView 配置
|
|
93
|
+
const vars = (await meta.buildVariablesParams!(ctx)) as any;
|
|
94
|
+
expect(vars).toBeTruthy();
|
|
95
|
+
expect(vars.record).toEqual({ collection: 'posts', dataSourceKey: 'main', filterByTk: 111 });
|
|
96
|
+
|
|
97
|
+
// 确认没有误用 ctx.view(settings-uid)的集合
|
|
98
|
+
expect(vars.record.collection).not.toBe('comments');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('properties() provides a record factory node (lazy) with title', async () => {
|
|
102
|
+
const { engine, ctx } = makeCtx();
|
|
103
|
+
// 只要能通过 anchorView 推断到集合名和主键即可;集合详情在懒加载时再取
|
|
104
|
+
const anchorView: FlowView = {
|
|
105
|
+
type: 'embed',
|
|
106
|
+
inputArgs: {},
|
|
107
|
+
Header: null,
|
|
108
|
+
Footer: null,
|
|
109
|
+
close: () => void 0,
|
|
110
|
+
update: () => void 0,
|
|
111
|
+
navigation: { viewStack: [{ viewUid: 'popup-uid', filterByTk: 1 }] } as any,
|
|
112
|
+
} as any;
|
|
113
|
+
const popupModel = {
|
|
114
|
+
getStepParams: vi.fn((_fk: string, sk: string) =>
|
|
115
|
+
sk === 'openView'
|
|
116
|
+
? {
|
|
117
|
+
collectionName: 'tasks',
|
|
118
|
+
dataSourceKey: 'main',
|
|
119
|
+
}
|
|
120
|
+
: undefined,
|
|
121
|
+
),
|
|
122
|
+
} as any;
|
|
123
|
+
vi.spyOn(engine as any, 'getModel').mockImplementation(() => popupModel);
|
|
124
|
+
|
|
125
|
+
const meta = (await createPopupMeta(ctx, anchorView)())!;
|
|
126
|
+
const props = typeof meta.properties === 'function' ? await (meta.properties as any)() : meta.properties || {};
|
|
127
|
+
// 断言存在 record 节点工厂,且有标题(懒加载,不触发集合访问)
|
|
128
|
+
expect(typeof props.record).toBe('function');
|
|
129
|
+
expect((props.record as any).title).toBe('Current popup record');
|
|
130
|
+
expect((props.record as any).hasChildren).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -1282,6 +1282,58 @@ describe('FlowContext resolveOnServer selective server resolution', () => {
|
|
|
1282
1282
|
// server was called
|
|
1283
1283
|
expect(api.request).toHaveBeenCalledTimes(1);
|
|
1284
1284
|
});
|
|
1285
|
+
|
|
1286
|
+
it('skips server call when all vars require contextParams but none provided', async () => {
|
|
1287
|
+
const engine = new FlowEngine();
|
|
1288
|
+
const api = { request: vi.fn() } as any;
|
|
1289
|
+
engine.context.defineProperty('api', { value: api });
|
|
1290
|
+
|
|
1291
|
+
engine.context.defineProperty('foo', {
|
|
1292
|
+
value: { a: 1 },
|
|
1293
|
+
resolveOnServer: true,
|
|
1294
|
+
serverOnlyWhenContextParams: true,
|
|
1295
|
+
meta: async () => ({
|
|
1296
|
+
type: 'object',
|
|
1297
|
+
title: 'Foo',
|
|
1298
|
+
// no buildVariablesParams -> empty contextParams
|
|
1299
|
+
}),
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
const tpl = { a: '{{ ctx.foo.a }}' } as any;
|
|
1303
|
+
const out = await (engine.context as any).resolveJsonTemplate(tpl);
|
|
1304
|
+
expect(out).toEqual({ a: 1 });
|
|
1305
|
+
// skipped server, because all server vars (only foo) require contextParams but none present
|
|
1306
|
+
expect(api.request).not.toHaveBeenCalled();
|
|
1307
|
+
});
|
|
1308
|
+
|
|
1309
|
+
it('still calls server when at least one var has contextParams (even if others require contextParams but none)', async () => {
|
|
1310
|
+
const engine = new FlowEngine();
|
|
1311
|
+
const api = { request: vi.fn(async () => ({ data: { ok: true } })) } as any;
|
|
1312
|
+
engine.context.defineProperty('api', { value: api });
|
|
1313
|
+
|
|
1314
|
+
// foo: requires contextParams but none will be provided
|
|
1315
|
+
engine.context.defineProperty('foo', {
|
|
1316
|
+
value: { a: 1 },
|
|
1317
|
+
resolveOnServer: true,
|
|
1318
|
+
serverOnlyWhenContextParams: true,
|
|
1319
|
+
meta: async () => ({ type: 'object', title: 'Foo' }),
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
// user: provides contextParams via builder
|
|
1323
|
+
engine.context.defineProperty('user', {
|
|
1324
|
+
value: { id: 9 },
|
|
1325
|
+
resolveOnServer: true,
|
|
1326
|
+
meta: async () => ({
|
|
1327
|
+
type: 'object',
|
|
1328
|
+
title: 'User',
|
|
1329
|
+
buildVariablesParams: () => ({ collection: 'users', filterByTk: 9, dataSourceKey: 'main' }),
|
|
1330
|
+
}),
|
|
1331
|
+
});
|
|
1332
|
+
|
|
1333
|
+
const tpl = { a: '{{ ctx.foo.a }}', u: '{{ ctx.user.id }}' } as any;
|
|
1334
|
+
await (engine.context as any).resolveJsonTemplate(tpl);
|
|
1335
|
+
expect(api.request).toHaveBeenCalledTimes(1);
|
|
1336
|
+
});
|
|
1285
1337
|
});
|
|
1286
1338
|
|
|
1287
1339
|
describe('FlowContext.getPropertyOptions()', () => {
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
11
|
+
import { FlowEngineContext } from '../flowContext';
|
|
12
|
+
import { FlowEngine } from '../flowEngine';
|
|
13
|
+
import { JSRunner } from '../JSRunner';
|
|
14
|
+
|
|
15
|
+
describe('FlowContext async createJSRunner', () => {
|
|
16
|
+
let engine: FlowEngine;
|
|
17
|
+
let engineCtx: FlowEngineContext;
|
|
18
|
+
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
// Create minimal engine and context for testing
|
|
21
|
+
engine = new FlowEngine();
|
|
22
|
+
engineCtx = new FlowEngineContext(engine);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('createJSRunner method', () => {
|
|
26
|
+
it('should be async and return JSRunner instance', async () => {
|
|
27
|
+
const runner = await engineCtx.createJSRunner();
|
|
28
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should pass globals to JSRunner', async () => {
|
|
32
|
+
const customGlobals = { customVar: 'test' };
|
|
33
|
+
const runner = await engineCtx.createJSRunner({ globals: customGlobals });
|
|
34
|
+
const result = await runner.run('return customVar');
|
|
35
|
+
expect(result?.success).toBe(true);
|
|
36
|
+
expect(result?.value).toBe('test');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should always provide ctx in globals', async () => {
|
|
40
|
+
const runner = await engineCtx.createJSRunner();
|
|
41
|
+
const result = await runner.run('return typeof ctx !== "undefined"');
|
|
42
|
+
expect(result?.success).toBe(true);
|
|
43
|
+
expect(result?.value).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should support timeout option', async () => {
|
|
47
|
+
const runner = await engineCtx.createJSRunner({ timeoutMs: 100 });
|
|
48
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should select appropriate context based on model class', async () => {
|
|
52
|
+
// Test with JSBlockModel
|
|
53
|
+
const ctx = new FlowEngineContext(engine);
|
|
54
|
+
(ctx as any).defineProperty('model', {
|
|
55
|
+
value: { constructor: { name: 'JSBlockModel' } },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const runner = await ctx.createJSRunner();
|
|
59
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
60
|
+
|
|
61
|
+
// Check if ctx.element is accessible (specific to JSBlockModel)
|
|
62
|
+
const result = await runner.run('return typeof ctx !== "undefined"');
|
|
63
|
+
expect(result?.success).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should select JSFieldModel context correctly', async () => {
|
|
67
|
+
const ctx = new FlowEngineContext(engine);
|
|
68
|
+
(ctx as any).defineProperty('model', {
|
|
69
|
+
value: { constructor: { name: 'JSFieldModel' } },
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const runner = await ctx.createJSRunner();
|
|
73
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should select JSColumnModel context correctly', async () => {
|
|
77
|
+
const ctx = new FlowEngineContext(engine);
|
|
78
|
+
(ctx as any).defineProperty('model', {
|
|
79
|
+
value: { constructor: { name: 'JSColumnModel' } },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const runner = await ctx.createJSRunner();
|
|
83
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should fallback to base context for unknown model', async () => {
|
|
87
|
+
const ctx = new FlowEngineContext(engine);
|
|
88
|
+
(ctx as any).defineProperty('model', {
|
|
89
|
+
value: { constructor: { name: 'UnknownModel' } },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const runner = await ctx.createJSRunner();
|
|
93
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
94
|
+
|
|
95
|
+
// Should still have ctx
|
|
96
|
+
const result = await runner.run('return typeof ctx !== "undefined"');
|
|
97
|
+
expect(result?.success).toBe(true);
|
|
98
|
+
expect(result?.value).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should support version option', async () => {
|
|
102
|
+
const runner = await engineCtx.createJSRunner({ version: 'v1' } as any);
|
|
103
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should merge custom globals with ctx', async () => {
|
|
107
|
+
const runner = await engineCtx.createJSRunner({
|
|
108
|
+
globals: { foo: 'bar', baz: 123 },
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const result = await runner.run('return { hasCtx: typeof ctx !== "undefined", foo, baz }');
|
|
112
|
+
expect(result?.success).toBe(true);
|
|
113
|
+
expect(result?.value).toEqual({ hasCtx: true, foo: 'bar', baz: 123 });
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should execute async code successfully', async () => {
|
|
117
|
+
const runner = await engineCtx.createJSRunner();
|
|
118
|
+
const result = await runner.run(`
|
|
119
|
+
return new Promise(resolve => {
|
|
120
|
+
setTimeout(() => resolve('async result'), 10);
|
|
121
|
+
});
|
|
122
|
+
`);
|
|
123
|
+
expect(result?.success).toBe(true);
|
|
124
|
+
expect(result?.value).toBe('async result');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should handle errors gracefully', async () => {
|
|
128
|
+
const runner = await engineCtx.createJSRunner();
|
|
129
|
+
const result = await runner.run('throw new Error("test error")');
|
|
130
|
+
expect(result?.success).toBe(false);
|
|
131
|
+
expect(result?.error).toBeTruthy();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should respect timeout setting', async () => {
|
|
135
|
+
const runner = await engineCtx.createJSRunner({ timeoutMs: 50 });
|
|
136
|
+
const result = await runner.run(`
|
|
137
|
+
return new Promise(resolve => {
|
|
138
|
+
setTimeout(() => resolve('done'), 1000);
|
|
139
|
+
});
|
|
140
|
+
`);
|
|
141
|
+
// Should timeout before completing
|
|
142
|
+
expect(result?.success).toBe(false);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('setupRunJSContexts integration', () => {
|
|
147
|
+
it('should auto-setup contexts when createJSRunner is called', async () => {
|
|
148
|
+
// Even if setup wasn't called manually, createJSRunner should trigger it
|
|
149
|
+
const ctx = new FlowEngineContext(engine);
|
|
150
|
+
(ctx as any).defineProperty('model', {
|
|
151
|
+
value: { constructor: { name: 'JSBlockModel' } },
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const runner = await ctx.createJSRunner();
|
|
155
|
+
expect(runner).toBeInstanceOf(JSRunner);
|
|
156
|
+
|
|
157
|
+
// Verify context is properly initialized
|
|
158
|
+
const result = await runner.run('return typeof ctx !== "undefined"');
|
|
159
|
+
expect(result?.success).toBe(true);
|
|
160
|
+
expect(result?.value).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -47,6 +47,10 @@ class MockFlowModelRepository implements IFlowModelRepository {
|
|
|
47
47
|
async move(sourceId: string, targetId: string, position: 'before' | 'after'): Promise<void> {
|
|
48
48
|
// Mock implementation
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
async duplicate(uid: string): Promise<Record<string, any> | null> {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
describe('FlowEngine.saveModel concurrent save prevention', () => {
|