@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
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Collection, CollectionField } from '../data-source';
|
|
11
|
+
import _ from 'lodash';
|
|
12
|
+
import type { FlowContext, PropertyMeta, PropertyMetaFactory } from '../flowContext';
|
|
13
|
+
import { createCollectionContextMeta } from './createCollectionContextMeta';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 提取变量子路径的顶层字段名。
|
|
17
|
+
* 例如:
|
|
18
|
+
* - 'author.name' => 'author'
|
|
19
|
+
* - 'tags[0].name' => 'tags'
|
|
20
|
+
*
|
|
21
|
+
* @param subPath 变量在对象中的子路径字符串
|
|
22
|
+
* @returns 顶层字段名,找不到时返回 undefined
|
|
23
|
+
*/
|
|
24
|
+
function baseFieldNameOf(subPath: string): string | undefined {
|
|
25
|
+
if (!subPath) return undefined;
|
|
26
|
+
const m = subPath.match(/^([^.[]+)/);
|
|
27
|
+
return m?.[1];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 在集合中根据字段名查找字段定义,兼容 getField/getFields 两种方式。
|
|
32
|
+
*
|
|
33
|
+
* @param collection 集合对象
|
|
34
|
+
* @param name 字段名
|
|
35
|
+
* @returns 匹配的字段定义,找不到时返回 undefined
|
|
36
|
+
*/
|
|
37
|
+
function findFieldByName(collection: Collection | null | undefined, name?: string): CollectionField | undefined {
|
|
38
|
+
if (!collection || !name) return undefined;
|
|
39
|
+
const direct = collection.getField(name);
|
|
40
|
+
if (direct) return direct;
|
|
41
|
+
const fields = collection.getFields?.() || [];
|
|
42
|
+
return fields.find((f) => f.name === name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 从值中提取主键:
|
|
47
|
+
* - 支持主键原始值(string/number)
|
|
48
|
+
* - 支持对象(按主键名取值)
|
|
49
|
+
*
|
|
50
|
+
* @param value 字段当前值
|
|
51
|
+
* @param primaryKey 主键字段名
|
|
52
|
+
* @returns 解析出的主键值,无法解析时返回 undefined
|
|
53
|
+
*/
|
|
54
|
+
function toFilterByTk(value: unknown, primaryKey: string | string[]) {
|
|
55
|
+
if (value == null) return undefined;
|
|
56
|
+
if (Array.isArray(primaryKey)) {
|
|
57
|
+
if (typeof value !== 'object' || !value) return undefined;
|
|
58
|
+
const out: Record<string, any> = {};
|
|
59
|
+
for (const k of primaryKey) {
|
|
60
|
+
const v = (value as any)[k];
|
|
61
|
+
if (typeof v === 'undefined' || v === null) return undefined;
|
|
62
|
+
out[k] = v;
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
if (typeof value === 'string' || typeof value === 'number') return value;
|
|
67
|
+
if (typeof value === 'object') {
|
|
68
|
+
return (value as any)[primaryKey];
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 创建一个用于“对象类变量”(如 formValues / currentObject)的 `resolveOnServer` 判定函数。
|
|
75
|
+
* 仅当访问路径以“关联字段名”开头(且继续访问其子属性)时,返回 true 交由服务端解析;
|
|
76
|
+
* 否则在前端解析即可。
|
|
77
|
+
*
|
|
78
|
+
* @param collectionAccessor 返回当前对象所在 collection
|
|
79
|
+
* @param valueAccessor 可选,本地值访问器。若本地已存在目标子路径的值,则认为无需走后端,优先使用本地值。
|
|
80
|
+
* @returns `(subPath) => boolean` 判断是否需要服务端解析
|
|
81
|
+
*/
|
|
82
|
+
export function createAssociationSubpathResolver(
|
|
83
|
+
collectionAccessor: () => Collection | null,
|
|
84
|
+
valueAccessor?: () => unknown,
|
|
85
|
+
): (subPath: string) => boolean {
|
|
86
|
+
return (p: string) => {
|
|
87
|
+
// 仅在访问子属性时才考虑后端
|
|
88
|
+
if (!p || !p.includes('.')) return false;
|
|
89
|
+
const base = baseFieldNameOf(p);
|
|
90
|
+
if (!base) return false;
|
|
91
|
+
const collection = collectionAccessor();
|
|
92
|
+
const field = findFieldByName(collection, base);
|
|
93
|
+
const isAssoc = !!field?.isAssociationField();
|
|
94
|
+
if (!isAssoc) return false;
|
|
95
|
+
|
|
96
|
+
// 可选:本地优先。当提供 valueAccessor 时,若本地已有该子路径值,则不走后端
|
|
97
|
+
if (typeof valueAccessor === 'function') {
|
|
98
|
+
const local = valueAccessor();
|
|
99
|
+
if (local && typeof local === 'object') {
|
|
100
|
+
const v = _.get(local as Record<string, unknown>, p);
|
|
101
|
+
if (typeof v !== 'undefined') return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return true;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 构建“对象类变量”的 PropertyMetaFactory:
|
|
111
|
+
* - 暴露集合字段结构(通过 createCollectionContextMeta)用于变量选择器;
|
|
112
|
+
* - 提供 buildVariablesParams:基于对象当前值,收集所有“已选择的关联字段”
|
|
113
|
+
* 以便服务端在 variables:resolve 时按需补全关联数据。
|
|
114
|
+
*
|
|
115
|
+
* @param collectionAccessor 获取集合对象,用于字段/元信息来源
|
|
116
|
+
* @param title 变量组标题(用于 UI 展示)
|
|
117
|
+
* @param valueAccessor 获取当前对象值(如 ctx.form.getFieldsValue() / ctx.currentObject)
|
|
118
|
+
* @returns PropertyMetaFactory
|
|
119
|
+
*/
|
|
120
|
+
export function createAssociationAwareObjectMetaFactory(
|
|
121
|
+
collectionAccessor: () => Collection | null,
|
|
122
|
+
title: string,
|
|
123
|
+
valueAccessor: (ctx: FlowContext) => any,
|
|
124
|
+
): PropertyMetaFactory {
|
|
125
|
+
const baseFactory = createCollectionContextMeta(collectionAccessor, title, true);
|
|
126
|
+
const factory: PropertyMetaFactory = async () => {
|
|
127
|
+
const base = (await baseFactory()) as PropertyMeta | null;
|
|
128
|
+
if (!base) return null;
|
|
129
|
+
|
|
130
|
+
const meta: PropertyMeta = {
|
|
131
|
+
...base,
|
|
132
|
+
buildVariablesParams: (ctx: FlowContext) => {
|
|
133
|
+
const collection = collectionAccessor();
|
|
134
|
+
const obj = valueAccessor(ctx);
|
|
135
|
+
if (!collection || !obj || typeof obj !== 'object') return {};
|
|
136
|
+
const params: Record<string, any> = {};
|
|
137
|
+
|
|
138
|
+
const fields: CollectionField[] = collection.getFields?.() || [];
|
|
139
|
+
for (const field of fields) {
|
|
140
|
+
const name = field.name as string | undefined;
|
|
141
|
+
if (!name) continue;
|
|
142
|
+
if (!field.isAssociationField()) continue;
|
|
143
|
+
const target = field.target as string | undefined;
|
|
144
|
+
const targetCollection = field.targetCollection;
|
|
145
|
+
if (!target || !targetCollection) continue;
|
|
146
|
+
const primaryKey = targetCollection.filterTargetKey as string | string[];
|
|
147
|
+
|
|
148
|
+
const associationValue = (obj as any)[name];
|
|
149
|
+
if (associationValue == null) continue;
|
|
150
|
+
|
|
151
|
+
if (Array.isArray(associationValue)) {
|
|
152
|
+
const ids = associationValue.map((item) => toFilterByTk(item, primaryKey)).filter((v) => v != null);
|
|
153
|
+
if (ids.length) {
|
|
154
|
+
params[name] = {
|
|
155
|
+
collection: target,
|
|
156
|
+
dataSourceKey: targetCollection.dataSourceKey,
|
|
157
|
+
filterByTk: ids,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
const id = toFilterByTk(associationValue, primaryKey);
|
|
162
|
+
if (id != null) {
|
|
163
|
+
params[name] = {
|
|
164
|
+
collection: target,
|
|
165
|
+
dataSourceKey: targetCollection.dataSourceKey,
|
|
166
|
+
filterByTk: id,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return params;
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return meta;
|
|
177
|
+
};
|
|
178
|
+
factory.title = title;
|
|
179
|
+
return factory;
|
|
180
|
+
}
|
|
@@ -17,7 +17,7 @@ const NUMERIC_FIELD_TYPES = ['integer', 'float', 'double', 'decimal'] as const;
|
|
|
17
17
|
/**
|
|
18
18
|
* 创建字段的完整元数据(统一处理关联和非关联字段)
|
|
19
19
|
*/
|
|
20
|
-
function createFieldMetadata(field: CollectionField) {
|
|
20
|
+
function createFieldMetadata(field: CollectionField, includeNonFilterable?: boolean) {
|
|
21
21
|
const baseProperties = createMetaBaseProperties(field);
|
|
22
22
|
|
|
23
23
|
if (field.isAssociationField()) {
|
|
@@ -36,7 +36,9 @@ function createFieldMetadata(field: CollectionField) {
|
|
|
36
36
|
properties: async () => {
|
|
37
37
|
const subProperties: Record<string, any> = {};
|
|
38
38
|
targetCollection.fields.forEach((subField) => {
|
|
39
|
-
|
|
39
|
+
if (includeNonFilterable || subField.filterable) {
|
|
40
|
+
subProperties[subField.name] = createFieldMetadata(subField, includeNonFilterable);
|
|
41
|
+
}
|
|
40
42
|
});
|
|
41
43
|
return subProperties;
|
|
42
44
|
},
|
|
@@ -86,6 +88,7 @@ function createMetaBaseProperties(field: CollectionField) {
|
|
|
86
88
|
return {
|
|
87
89
|
title: field.title || field.name,
|
|
88
90
|
interface: field.interface,
|
|
91
|
+
options: field.options,
|
|
89
92
|
uiSchema: field.uiSchema || {},
|
|
90
93
|
};
|
|
91
94
|
}
|
|
@@ -93,6 +96,7 @@ function createMetaBaseProperties(field: CollectionField) {
|
|
|
93
96
|
export function createCollectionContextMeta(
|
|
94
97
|
collectionOrFactory: Collection | (() => Collection | null),
|
|
95
98
|
title?: string,
|
|
99
|
+
includeNonFilterable?: boolean,
|
|
96
100
|
): PropertyMetaFactory {
|
|
97
101
|
const metaFn: PropertyMetaFactory = async () => {
|
|
98
102
|
const collection = typeof collectionOrFactory === 'function' ? collectionOrFactory() : collectionOrFactory;
|
|
@@ -110,7 +114,9 @@ export function createCollectionContextMeta(
|
|
|
110
114
|
|
|
111
115
|
// 添加所有字段
|
|
112
116
|
collection.fields.forEach((field) => {
|
|
113
|
-
|
|
117
|
+
if (includeNonFilterable || field.filterable) {
|
|
118
|
+
properties[field.name] = createFieldMetadata(field, includeNonFilterable);
|
|
119
|
+
}
|
|
114
120
|
});
|
|
115
121
|
|
|
116
122
|
return properties;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { FlowContext } from '../flowContext';
|
|
11
|
+
import type { ActionDefinition } from '../types';
|
|
12
|
+
import type { PropertyOptions } from '../flowContext';
|
|
13
|
+
|
|
14
|
+
// 临时上下文:
|
|
15
|
+
// - 读:优先从 scoped(临时定义)读取,兜底 parent;
|
|
16
|
+
// - 写:统一写入 parent(不污染 scoped);
|
|
17
|
+
// - 注入:create 阶段 define* 写入 scoped;运行阶段 define* 写入 parent。
|
|
18
|
+
type ContextDefsLike<TCtx extends FlowContext> =
|
|
19
|
+
| Partial<Pick<ActionDefinition<any, TCtx>, 'defineProperties' | 'defineMethods'>>
|
|
20
|
+
| null
|
|
21
|
+
| undefined;
|
|
22
|
+
|
|
23
|
+
export async function createEphemeralContext<TCtx extends FlowContext>(
|
|
24
|
+
parent: TCtx,
|
|
25
|
+
contextDefs?: ContextDefsLike<TCtx>,
|
|
26
|
+
): Promise<TCtx> {
|
|
27
|
+
// 若未提供任何上下文定义,直接复用父级上下文,避免不必要的代理包装
|
|
28
|
+
if (contextDefs == null || (!contextDefs.defineProperties && !contextDefs.defineMethods)) {
|
|
29
|
+
return parent;
|
|
30
|
+
}
|
|
31
|
+
// 1) 创建一个新的 FlowContext,专门承载“临时定义”(defineProperty/defineMethod)
|
|
32
|
+
const scoped = new FlowContext();
|
|
33
|
+
// 2) 读取优先:先从 scoped 自身取(_props/_methods),否则委托到 parent(仅 _props/_methods)
|
|
34
|
+
scoped.addDelegate(parent);
|
|
35
|
+
|
|
36
|
+
// 3) 先创建 scoped 的代理,用于注入阶段(define* 直达 scoped;读写行为与最终代理一致)
|
|
37
|
+
const scopedProxy = scoped.createProxy();
|
|
38
|
+
const scopedObj = scopedProxy as unknown as object;
|
|
39
|
+
const parentObj = parent as unknown as object;
|
|
40
|
+
const getFromParent = (key: PropertyKey) => {
|
|
41
|
+
const val = Reflect.get(parentObj, key, parentObj);
|
|
42
|
+
return typeof val === 'function' ? (val as Function).bind(parent) : val;
|
|
43
|
+
};
|
|
44
|
+
const hasInScopedOrParent = (key: PropertyKey) =>
|
|
45
|
+
key === 'defineProperty' || key === 'defineMethod' || Reflect.has(scopedObj, key) || Reflect.has(parentObj, key);
|
|
46
|
+
const injectionProxy = new Proxy(scopedProxy as TCtx, {
|
|
47
|
+
get(_t, key: PropertyKey, receiver) {
|
|
48
|
+
if (typeof key === 'string') {
|
|
49
|
+
// 注入阶段:允许在 defLike 的函数体中调用 ctx.defineProperty/defineMethod 写入 scoped
|
|
50
|
+
if (key === 'defineProperty') {
|
|
51
|
+
return (propKey: string, options: any) => (scoped as FlowContext).defineProperty(propKey, options);
|
|
52
|
+
}
|
|
53
|
+
if (key === 'defineMethod') {
|
|
54
|
+
return (name: string, fn: any, des?: string) => (scoped as FlowContext).defineMethod(name, fn, des);
|
|
55
|
+
}
|
|
56
|
+
if (Reflect.has(scopedObj, key)) {
|
|
57
|
+
return Reflect.get(scopedObj, key, receiver);
|
|
58
|
+
}
|
|
59
|
+
return getFromParent(key);
|
|
60
|
+
}
|
|
61
|
+
return Reflect.get(scopedObj, key, receiver);
|
|
62
|
+
},
|
|
63
|
+
set(_t, key: PropertyKey, value: unknown) {
|
|
64
|
+
return Reflect.set(parentObj, key, value);
|
|
65
|
+
},
|
|
66
|
+
has(_t, key: PropertyKey) {
|
|
67
|
+
return hasInScopedOrParent(key);
|
|
68
|
+
},
|
|
69
|
+
getOwnPropertyDescriptor(_t, key: PropertyKey) {
|
|
70
|
+
return Object.getOwnPropertyDescriptor(scopedObj, key) || Object.getOwnPropertyDescriptor(parentObj, key);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// 如果提供了 contextDefs,则在创建时即注入定义,便于外部更简洁地使用
|
|
75
|
+
if (contextDefs) {
|
|
76
|
+
const defs = Array.isArray(contextDefs) ? contextDefs : [contextDefs];
|
|
77
|
+
for (const defLike of defs) {
|
|
78
|
+
if (!defLike) continue;
|
|
79
|
+
// 1) defineProperties -> 写入到 scoped(避免污染父级)
|
|
80
|
+
const dp = (defLike as any).defineProperties;
|
|
81
|
+
if (dp) {
|
|
82
|
+
const raw = typeof dp === 'function' ? await dp(injectionProxy as TCtx) : dp;
|
|
83
|
+
if (!raw || typeof raw !== 'object') {
|
|
84
|
+
throw new TypeError('defineProperties must return an object of PropertyOptions');
|
|
85
|
+
}
|
|
86
|
+
const propsDef = raw as Record<string, PropertyOptions>;
|
|
87
|
+
for (const [key, options] of Object.entries(propsDef)) {
|
|
88
|
+
if (!options || typeof options !== 'object') {
|
|
89
|
+
throw new TypeError(`defineProperties['${key}'] must be a PropertyOptions object`);
|
|
90
|
+
}
|
|
91
|
+
// 直接在 scoped 上定义,确保仅限本次临时作用域
|
|
92
|
+
(scoped as FlowContext).defineProperty(key, options);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// 2) defineMethods -> 写入到 scoped(避免污染父级)
|
|
96
|
+
const dm = (defLike as any).defineMethods;
|
|
97
|
+
if (dm) {
|
|
98
|
+
const raw = typeof dm === 'function' ? await dm(injectionProxy as TCtx) : dm;
|
|
99
|
+
if (!raw || typeof raw !== 'object') {
|
|
100
|
+
throw new TypeError('defineMethods must return an object of functions');
|
|
101
|
+
}
|
|
102
|
+
const methodsDef = raw as Record<string, (this: TCtx, ...args: any[]) => any>;
|
|
103
|
+
for (const [key, fn] of Object.entries(methodsDef)) {
|
|
104
|
+
if (typeof fn !== 'function') {
|
|
105
|
+
throw new TypeError(`defineMethods['${key}'] must be a function`);
|
|
106
|
+
}
|
|
107
|
+
(scoped as FlowContext).defineMethod(key, fn as any);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 4) 创建最终对外代理:读取优先 scoped,兜底父级,且后续 define* 写入父级
|
|
114
|
+
const outerProxy = new Proxy(scopedProxy as TCtx, {
|
|
115
|
+
get(_t, key: PropertyKey, receiver) {
|
|
116
|
+
if (typeof key === 'string') {
|
|
117
|
+
if (key === 'defineProperty') {
|
|
118
|
+
return (propKey: string, options: any) => (parent as FlowContext).defineProperty(propKey, options);
|
|
119
|
+
}
|
|
120
|
+
if (key === 'defineMethod') {
|
|
121
|
+
return (name: string, fn: any, des?: string) => (parent as FlowContext).defineMethod(name, fn, des);
|
|
122
|
+
}
|
|
123
|
+
if (Reflect.has(scopedObj, key)) {
|
|
124
|
+
return Reflect.get(scopedObj, key, receiver);
|
|
125
|
+
}
|
|
126
|
+
return getFromParent(key);
|
|
127
|
+
}
|
|
128
|
+
return Reflect.get(scopedObj, key, receiver);
|
|
129
|
+
},
|
|
130
|
+
set(_t, key: PropertyKey, value: unknown) {
|
|
131
|
+
return Reflect.set(parentObj, key, value);
|
|
132
|
+
},
|
|
133
|
+
has(_t, key: PropertyKey) {
|
|
134
|
+
return hasInScopedOrParent(key);
|
|
135
|
+
},
|
|
136
|
+
getOwnPropertyDescriptor(_t, key: PropertyKey) {
|
|
137
|
+
return Object.getOwnPropertyDescriptor(scopedObj, key) || Object.getOwnPropertyDescriptor(parentObj, key);
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return outerProxy as TCtx;
|
|
142
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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 { FlowDefinition } from '../FlowDefinition';
|
|
11
|
+
|
|
12
|
+
export const isBeforeRenderFlow = (flow: FlowDefinition): boolean => {
|
|
13
|
+
if (typeof flow.on === 'string') {
|
|
14
|
+
return flow.on === 'beforeRender';
|
|
15
|
+
}
|
|
16
|
+
if (typeof flow.on === 'object') {
|
|
17
|
+
return flow.on.eventName === 'beforeRender';
|
|
18
|
+
}
|
|
19
|
+
if (!flow.on && flow.manual !== true) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
package/src/utils/index.ts
CHANGED
|
@@ -34,21 +34,22 @@ export { isInheritedFrom } from './inheritance';
|
|
|
34
34
|
export { resolveCreateModelOptions, resolveDefaultParams, resolveExpressions } from './params-resolvers';
|
|
35
35
|
|
|
36
36
|
// Schema 工具
|
|
37
|
-
export { compileUiSchema, resolveStepUiSchema, resolveUiMode } from './schema-utils';
|
|
37
|
+
export { compileUiSchema, resolveStepUiSchema, resolveUiMode, shouldHideStepInSettings } from './schema-utils';
|
|
38
38
|
|
|
39
39
|
// Runtime Context Steps 设置
|
|
40
40
|
export { setupRuntimeContextSteps } from './setupRuntimeContextSteps';
|
|
41
41
|
|
|
42
42
|
// Record Proxy 工具
|
|
43
43
|
export { createCollectionContextMeta } from './createCollectionContextMeta';
|
|
44
|
+
export { createAssociationAwareObjectMetaFactory, createAssociationSubpathResolver } from './associationObjectVariable';
|
|
44
45
|
export {
|
|
45
46
|
buildRecordMeta,
|
|
46
47
|
collectContextParamsForTemplate,
|
|
47
48
|
createCurrentRecordMetaFactory,
|
|
49
|
+
createRecordResolveOnServerWithLocal,
|
|
48
50
|
createRecordMetaFactory,
|
|
49
51
|
extractUsedVariableNames,
|
|
50
52
|
extractUsedVariablePaths,
|
|
51
|
-
inferParentRecordRef,
|
|
52
53
|
inferRecordRef,
|
|
53
54
|
type RecordParamsBuilder,
|
|
54
55
|
} from './variablesParams';
|
|
@@ -60,4 +61,17 @@ export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowEr
|
|
|
60
61
|
export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
|
|
61
62
|
|
|
62
63
|
// 安全全局对象(window/document)
|
|
63
|
-
export { createSafeDocument, createSafeWindow } from './safeGlobals';
|
|
64
|
+
export { createSafeDocument, createSafeWindow, createSafeNavigator } from './safeGlobals';
|
|
65
|
+
|
|
66
|
+
// RunJS 代码兼容预处理({{ }})与 JSX 编译
|
|
67
|
+
export { prepareRunJsCode, preprocessRunJsTemplates } from './runjsTemplateCompat';
|
|
68
|
+
|
|
69
|
+
// Ephemeral context helper(用于临时注入属性/方法,避免污染父级 ctx)
|
|
70
|
+
export { createEphemeralContext } from './createEphemeralContext';
|
|
71
|
+
|
|
72
|
+
// Filter helpers
|
|
73
|
+
export { pruneFilter } from './pruneFilter';
|
|
74
|
+
export { isBeforeRenderFlow } from './flows';
|
|
75
|
+
|
|
76
|
+
// Module URL resolver
|
|
77
|
+
export { resolveModuleUrl, isCssFile } from './resolveModuleUrl';
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
/**
|
|
11
|
+
* Lightweight JSX -> JS compiler for RunJS user code.
|
|
12
|
+
* - Uses sucrase via dynamic import (lazy; avoids static cycles and cost when not needed)
|
|
13
|
+
* - Maps JSX to ctx.React.createElement / ctx.React.Fragment so no global React is required
|
|
14
|
+
* - If sucrase is unavailable or transform throws, returns original code as graceful fallback
|
|
15
|
+
*/
|
|
16
|
+
export async function compileRunJs(code: string): Promise<string> {
|
|
17
|
+
// Fast path: cheap heuristic to skip import if no JSX likely present
|
|
18
|
+
// (not strict; still safe because we fall back to transform if dynamic import is cheap)
|
|
19
|
+
const maybeJSX = /<[A-Za-z]|<\//.test(code);
|
|
20
|
+
if (!maybeJSX) return code;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const mod: any = await import('sucrase');
|
|
24
|
+
const transform = mod?.transform || mod?.default?.transform;
|
|
25
|
+
if (typeof transform !== 'function') return code;
|
|
26
|
+
const res = transform(code, {
|
|
27
|
+
transforms: ['jsx'],
|
|
28
|
+
jsxPragma: 'ctx.React.createElement',
|
|
29
|
+
jsxFragmentPragma: 'ctx.React.Fragment',
|
|
30
|
+
// Keep ES syntax as-is; JSRunner runs in modern engines
|
|
31
|
+
disableESTransforms: true,
|
|
32
|
+
production: true,
|
|
33
|
+
});
|
|
34
|
+
return (res && (res.code || res?.output)) ?? code;
|
|
35
|
+
} catch (_e) {
|
|
36
|
+
// Fallback: return original code if transform fails
|
|
37
|
+
return code;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { getValuesByPath } from '@nocobase/shared';
|
|
10
11
|
import _ from 'lodash';
|
|
11
12
|
import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContext';
|
|
12
|
-
import { getValuesByPath } from '@nocobase/utils/client';
|
|
13
13
|
import type { FlowModel } from '../models';
|
|
14
14
|
import type { ServerContextParams } from './serverContextParams';
|
|
15
15
|
|
|
@@ -409,8 +409,13 @@ export async function preprocessExpression(expression: string, ctx: FlowContext)
|
|
|
409
409
|
async function compileExpression<TModel extends FlowModel = FlowModel>(expression: string, ctx: FlowContext) {
|
|
410
410
|
// 仅点号路径匹配:ctx.a.b.c(不支持括号/函数/索引),用于数组聚合取值
|
|
411
411
|
const matchDotOnly = (expr: string): string | null => {
|
|
412
|
-
|
|
413
|
-
|
|
412
|
+
// 顶层变量名仍使用 JS 标识符规则(与 ctx.defineProperty 保持一致);
|
|
413
|
+
// 子路径允许包含 '-'(例如 formValues.oho-test.o2m-users)。
|
|
414
|
+
const m = expr
|
|
415
|
+
.trim()
|
|
416
|
+
.match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)(?:\.([a-zA-Z_$][a-zA-Z0-9_$-]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$-]*)*))?$/);
|
|
417
|
+
if (!m) return null;
|
|
418
|
+
return m[2] ? `${m[1]}.${m[2]}` : m[1];
|
|
414
419
|
};
|
|
415
420
|
|
|
416
421
|
// 基于 getValuesByPath 的聚合取值:支持数组扁平化,仅支持 '.' 访问
|
|
@@ -423,6 +428,20 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
|
|
|
423
428
|
return getValuesByPath(base as object, segs.join('.'));
|
|
424
429
|
};
|
|
425
430
|
|
|
431
|
+
const resolveInnerExpression = async (innerExpr: string): Promise<any> => {
|
|
432
|
+
const dotPath = matchDotOnly(innerExpr);
|
|
433
|
+
if (dotPath) {
|
|
434
|
+
const resolved = await resolveDotOnlyPath(dotPath);
|
|
435
|
+
// 当 dotPath 含 '-' 时可能与减号运算符存在歧义,例如:ctx.aa.bb-ctx.cc。
|
|
436
|
+
// 若按 path 解析未取到值,则回退到 JS 表达式解析,尽量保持兼容。
|
|
437
|
+
if (resolved === undefined && dotPath.includes('-')) {
|
|
438
|
+
return await processExpression(innerExpr, ctx);
|
|
439
|
+
}
|
|
440
|
+
return resolved;
|
|
441
|
+
}
|
|
442
|
+
return await processExpression(innerExpr, ctx);
|
|
443
|
+
};
|
|
444
|
+
|
|
426
445
|
/**
|
|
427
446
|
* 单个表达式模式匹配
|
|
428
447
|
*
|
|
@@ -440,14 +459,10 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
|
|
|
440
459
|
* ✅ "{{ctx.user}}" -> 捕获: "ctx.user"
|
|
441
460
|
* ❌ "Hello {{ ctx.user }}" -> 不匹配(不是纯表达式)
|
|
442
461
|
*/
|
|
443
|
-
const singleMatch = expression.match(/^\{\{\s*(
|
|
462
|
+
const singleMatch = expression.match(/^\s*\{\{\s*([^{}]+?)\s*\}\}\s*$/);
|
|
444
463
|
if (singleMatch) {
|
|
445
464
|
const inner = singleMatch[1];
|
|
446
|
-
|
|
447
|
-
if (dotPath) {
|
|
448
|
-
return await resolveDotOnlyPath(dotPath);
|
|
449
|
-
}
|
|
450
|
-
return await processExpression(inner, ctx);
|
|
465
|
+
return await resolveInnerExpression(inner);
|
|
451
466
|
}
|
|
452
467
|
|
|
453
468
|
/**
|
|
@@ -470,8 +485,7 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
|
|
|
470
485
|
let result = expression;
|
|
471
486
|
|
|
472
487
|
for (const [fullMatch, innerExpr] of matches) {
|
|
473
|
-
const
|
|
474
|
-
const value = dotPath ? await resolveDotOnlyPath(dotPath) : await processExpression(innerExpr, ctx);
|
|
488
|
+
const value = await resolveInnerExpression(innerExpr);
|
|
475
489
|
if (value !== undefined) {
|
|
476
490
|
const replacement = typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);
|
|
477
491
|
result = result.replace(fullMatch, replacement);
|
|
@@ -13,7 +13,7 @@ export interface ViewParam {
|
|
|
13
13
|
/** 标签页唯一标识符 */
|
|
14
14
|
tabUid?: string;
|
|
15
15
|
/** 弹窗记录的 id */
|
|
16
|
-
filterByTk?: string
|
|
16
|
+
filterByTk?: string | Record<string, string | number>;
|
|
17
17
|
/** source Id */
|
|
18
18
|
sourceId?: string;
|
|
19
19
|
}
|
|
@@ -70,17 +70,61 @@ export const parsePathnameToViewParams = (pathname: string): ViewParam[] => {
|
|
|
70
70
|
}
|
|
71
71
|
// 处理参数
|
|
72
72
|
else if (currentView && i + 1 < segments.length) {
|
|
73
|
-
const
|
|
73
|
+
const rawValue = segments[i + 1];
|
|
74
|
+
// 尝试对路径段进行解码
|
|
75
|
+
let decoded: string = rawValue;
|
|
76
|
+
try {
|
|
77
|
+
decoded = decodeURIComponent(rawValue);
|
|
78
|
+
} catch (_) {
|
|
79
|
+
// ignore
|
|
80
|
+
}
|
|
74
81
|
|
|
75
82
|
switch (segment) {
|
|
76
83
|
case 'tab':
|
|
77
|
-
|
|
84
|
+
// tab/sourceId 仅作为字符串处理
|
|
85
|
+
currentView.tabUid = decoded;
|
|
78
86
|
break;
|
|
79
|
-
case 'filterbytk':
|
|
80
|
-
|
|
87
|
+
case 'filterbytk': {
|
|
88
|
+
// 仅在 filterByTk 分支支持对象/JSON/键值对解析
|
|
89
|
+
const parseKeyValuePairs = (s: string): Record<string, string | number> => {
|
|
90
|
+
const obj: Record<string, string | number> = {};
|
|
91
|
+
s.split('&').forEach((pair) => {
|
|
92
|
+
const [k, v = ''] = pair.split('=');
|
|
93
|
+
if (!k) return;
|
|
94
|
+
try {
|
|
95
|
+
const key = decodeURIComponent(k);
|
|
96
|
+
const val = decodeURIComponent(v);
|
|
97
|
+
obj[key] = val;
|
|
98
|
+
} catch (_) {
|
|
99
|
+
obj[k] = v;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return obj;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
let parsed: string | Record<string, string | number> = decoded;
|
|
106
|
+
if (decoded && (decoded.startsWith('{') || decoded.startsWith('['))) {
|
|
107
|
+
try {
|
|
108
|
+
const maybe = JSON.parse(decoded);
|
|
109
|
+
if (maybe && typeof maybe === 'object' && !Array.isArray(maybe)) {
|
|
110
|
+
parsed = maybe as Record<string, string | number>;
|
|
111
|
+
} else {
|
|
112
|
+
// 非对象 JSON(如数组/数字)按字符串保留
|
|
113
|
+
parsed = decoded;
|
|
114
|
+
}
|
|
115
|
+
} catch (_) {
|
|
116
|
+
// 解析失败,按字符串保留
|
|
117
|
+
parsed = decoded;
|
|
118
|
+
}
|
|
119
|
+
} else if (decoded && decoded.includes('=') && decoded.includes('&')) {
|
|
120
|
+
// 形如 a=b&c=d 的整体段
|
|
121
|
+
parsed = parseKeyValuePairs(decoded);
|
|
122
|
+
}
|
|
123
|
+
currentView.filterByTk = parsed;
|
|
81
124
|
break;
|
|
125
|
+
}
|
|
82
126
|
case 'sourceid':
|
|
83
|
-
currentView.sourceId =
|
|
127
|
+
currentView.sourceId = decoded;
|
|
84
128
|
break;
|
|
85
129
|
default:
|
|
86
130
|
// 未知参数,跳过
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
/**
|
|
11
|
+
* 递归清理筛选对象中的“空值”。
|
|
12
|
+
*
|
|
13
|
+
* 规则:
|
|
14
|
+
* - 移除:`null`、`undefined`、空字符串 `''`、空数组 `[]`、空对象 `{}`;
|
|
15
|
+
* - 保留:`false`、`0` 等有意义的“假值”。
|
|
16
|
+
*
|
|
17
|
+
* 注意:当清理后整体变为空结构时,返回 `undefined`,用于表示无需下发该条件。
|
|
18
|
+
*
|
|
19
|
+
* @param input 任意筛选对象/数组/原始值
|
|
20
|
+
* @returns 清理后的对象;若为空则返回 `undefined`
|
|
21
|
+
*/
|
|
22
|
+
export function pruneFilter<T = any>(input: T): T | undefined {
|
|
23
|
+
// Arrays: prune items and drop empty arrays
|
|
24
|
+
if (Array.isArray(input)) {
|
|
25
|
+
const arr = (input as unknown[]).map((v) => pruneFilter(v)).filter((v) => v !== undefined);
|
|
26
|
+
return (arr.length ? (arr as unknown as T) : undefined) as any;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Objects: prune properties and drop empty objects
|
|
30
|
+
if (input && typeof input === 'object') {
|
|
31
|
+
const out: Record<string, any> = {};
|
|
32
|
+
Object.keys(input as Record<string, any>).forEach((k) => {
|
|
33
|
+
const v = pruneFilter((input as any)[k]);
|
|
34
|
+
if (v !== undefined) out[k] = v;
|
|
35
|
+
});
|
|
36
|
+
return (Object.keys(out).length ? (out as unknown as T) : undefined) as any;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Primitives: keep false/0; drop null/undefined/''
|
|
40
|
+
return input === null || input === undefined || (typeof input === 'string' && input === '') ? undefined : input;
|
|
41
|
+
}
|