@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
package/src/flowContext.ts
CHANGED
|
@@ -11,14 +11,16 @@ import { ISchema } from '@formily/json-schema';
|
|
|
11
11
|
import { observable } from '@formily/reactive';
|
|
12
12
|
import { APIClient } from '@nocobase/sdk';
|
|
13
13
|
import type { Router } from '@remix-run/router';
|
|
14
|
-
import * as antd from 'antd';
|
|
15
14
|
import { MessageInstance } from 'antd/es/message/interface';
|
|
15
|
+
import * as antd from 'antd';
|
|
16
16
|
import type { HookAPI } from 'antd/es/modal/useModal';
|
|
17
17
|
import { NotificationInstance } from 'antd/es/notification/interface';
|
|
18
18
|
import _ from 'lodash';
|
|
19
19
|
import pino from 'pino';
|
|
20
20
|
import qs from 'qs';
|
|
21
21
|
import React, { createRef } from 'react';
|
|
22
|
+
import * as ReactDOMClient from 'react-dom/client';
|
|
23
|
+
import { ElementProxy } from './ElementProxy';
|
|
22
24
|
import type { Location } from 'react-router-dom';
|
|
23
25
|
import { ACL } from './acl/Acl';
|
|
24
26
|
import { ContextPathProxy } from './ContextPathProxy';
|
|
@@ -26,33 +28,32 @@ import { DataSource, DataSourceManager } from './data-source';
|
|
|
26
28
|
import { FlowEngine } from './flowEngine';
|
|
27
29
|
import { FlowI18n } from './flowI18n';
|
|
28
30
|
import { JSRunner, JSRunnerOptions } from './JSRunner';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
APIResource,
|
|
33
|
-
BaseRecordResource,
|
|
34
|
-
FlowResource,
|
|
35
|
-
FlowSQLRepository,
|
|
36
|
-
MultiRecordResource,
|
|
37
|
-
SingleRecordResource,
|
|
38
|
-
SQLResource,
|
|
39
|
-
} from './resources';
|
|
31
|
+
import type { FlowModel } from './models/flowModel';
|
|
32
|
+
import type { ForkFlowModel } from './models/forkFlowModel';
|
|
33
|
+
import { FlowResource, FlowSQLRepository } from './resources';
|
|
40
34
|
import type { ActionDefinition, EventDefinition, ResourceType } from './types';
|
|
41
35
|
import {
|
|
42
|
-
createSafeDocument,
|
|
43
|
-
createSafeWindow,
|
|
44
36
|
escapeT,
|
|
45
37
|
extractPropertyPath,
|
|
46
38
|
extractUsedVariablePaths,
|
|
47
39
|
FlowExitException,
|
|
40
|
+
isCssFile,
|
|
41
|
+
prepareRunJsCode,
|
|
48
42
|
resolveDefaultParams,
|
|
49
43
|
resolveExpressions,
|
|
44
|
+
resolveModuleUrl,
|
|
50
45
|
} from './utils';
|
|
51
46
|
import { FlowExitAllException } from './utils/exceptions';
|
|
52
47
|
import { enqueueVariablesResolve, JSONValue } from './utils/params-resolvers';
|
|
53
48
|
import type { RecordRef } from './utils/serverContextParams';
|
|
54
49
|
import { buildServerContextParams as _buildServerContextParams } from './utils/serverContextParams';
|
|
50
|
+
import { inferRecordRef } from './utils/variablesParams';
|
|
55
51
|
import { FlowView, FlowViewer } from './views/FlowView';
|
|
52
|
+
import { RunJSContextRegistry, getModelClassName } from './runjs-context/registry';
|
|
53
|
+
import { createEphemeralContext } from './utils/createEphemeralContext';
|
|
54
|
+
import dayjs from 'dayjs';
|
|
55
|
+
import { externalReactRender, setupRunJSLibs } from './runjsLibs';
|
|
56
|
+
import { runjsImportAsync, runjsImportModule, runjsRequireAsync } from './utils/runjsModuleLoader';
|
|
56
57
|
|
|
57
58
|
// Helper: detect a RecordRef-like object
|
|
58
59
|
function isRecordRefLike(val: any): boolean {
|
|
@@ -75,6 +76,61 @@ function filterBuilderOutputByPaths(built: any, neededPaths: string[]): any {
|
|
|
75
76
|
return undefined;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
// Helper: extract top-level segment of a subpath (e.g. 'a.b' -> 'a', 'tags[0].name' -> 'tags')
|
|
80
|
+
function topLevelOf(subPath: string): string | undefined {
|
|
81
|
+
if (!subPath) return undefined;
|
|
82
|
+
const m = String(subPath).match(/^([^.[]+)/);
|
|
83
|
+
return m?.[1];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Helper: infer selects (fields/appends) from usage paths (mirrors server-side inferSelectsFromUsage)
|
|
87
|
+
function inferSelectsFromUsage(paths: string[] = []): { generatedAppends?: string[]; generatedFields?: string[] } {
|
|
88
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
89
|
+
return { generatedAppends: undefined, generatedFields: undefined };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const appendSet = new Set<string>();
|
|
93
|
+
const fieldSet = new Set<string>();
|
|
94
|
+
|
|
95
|
+
const normalizePath = (raw: string): string => {
|
|
96
|
+
if (!raw) return '';
|
|
97
|
+
let s = String(raw);
|
|
98
|
+
// remove numeric indexes like [0]
|
|
99
|
+
s = s.replace(/\[(?:\d+)\]/g, '');
|
|
100
|
+
// normalize string indexes like ["name"] / ['name'] into .name
|
|
101
|
+
s = s.replace(/\[(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')\]/g, (_m, g1, g2) => `.${(g1 || g2) as string}`);
|
|
102
|
+
s = s.replace(/\.\.+/g, '.');
|
|
103
|
+
s = s.replace(/^\./, '').replace(/\.$/, '');
|
|
104
|
+
return s;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
for (let path of paths) {
|
|
108
|
+
if (!path) continue;
|
|
109
|
+
// drop leading numeric index like [0].name
|
|
110
|
+
while (/^\[(\d+)\](\.|$)/.test(path)) {
|
|
111
|
+
path = path.replace(/^\[(\d+)\]\.?/, '');
|
|
112
|
+
}
|
|
113
|
+
const norm = normalizePath(path);
|
|
114
|
+
if (!norm) continue;
|
|
115
|
+
const segments = norm.split('.').filter(Boolean);
|
|
116
|
+
if (segments.length === 0) continue;
|
|
117
|
+
|
|
118
|
+
if (segments.length === 1) {
|
|
119
|
+
fieldSet.add(segments[0]);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
124
|
+
appendSet.add(segments.slice(0, i + 1).join('.'));
|
|
125
|
+
}
|
|
126
|
+
fieldSet.add(segments.join('.'));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const generatedAppends = appendSet.size ? Array.from(appendSet) : undefined;
|
|
130
|
+
const generatedFields = fieldSet.size ? Array.from(fieldSet) : undefined;
|
|
131
|
+
return { generatedAppends, generatedFields };
|
|
132
|
+
}
|
|
133
|
+
|
|
78
134
|
type Getter<T = any> = (ctx: FlowContext) => T | Promise<T>;
|
|
79
135
|
|
|
80
136
|
export interface MetaTreeNode {
|
|
@@ -82,11 +138,14 @@ export interface MetaTreeNode {
|
|
|
82
138
|
title: string;
|
|
83
139
|
type: string;
|
|
84
140
|
interface?: string;
|
|
141
|
+
options?: any;
|
|
85
142
|
uiSchema?: ISchema;
|
|
86
143
|
render?: (props: any) => JSX.Element;
|
|
87
144
|
// display?: 'default' | 'flatten' | 'none'; // 显示模式:默认、平铺子菜单、完全隐藏, 用于简化meta树显示层级
|
|
88
145
|
paths: string[];
|
|
89
146
|
parentTitles?: string[]; // 父级标题数组,不包含自身title,第一层可省略
|
|
147
|
+
// 显示控制:当 hidden 为 true(或函数返回 true)时,不在变量选择器中展示该节点
|
|
148
|
+
hidden?: boolean | (() => boolean);
|
|
90
149
|
// 变量禁用状态与原因(用于变量选择器 UI 展示)
|
|
91
150
|
disabled?: boolean | (() => boolean);
|
|
92
151
|
disabledReason?: string | (() => string | undefined);
|
|
@@ -97,6 +156,7 @@ export interface PropertyMeta {
|
|
|
97
156
|
type: string;
|
|
98
157
|
title: string;
|
|
99
158
|
interface?: string;
|
|
159
|
+
options?: any;
|
|
100
160
|
uiSchema?: ISchema; // TODO: 这个是不是压根没必要啊?
|
|
101
161
|
render?: (props: any) => JSX.Element; // 自定义渲染函数
|
|
102
162
|
// 用于 VariableInput 的排序:数值越大,显示越靠前;相同值保持稳定顺序
|
|
@@ -107,6 +167,8 @@ export interface PropertyMeta {
|
|
|
107
167
|
disabled?: boolean | (() => boolean);
|
|
108
168
|
// 禁用原因(用于 UI 小问号提示),可为函数
|
|
109
169
|
disabledReason?: string | (() => string | undefined);
|
|
170
|
+
// 显示控制:当 hidden 为 true(或函数返回 true)时,不在变量选择器中展示该节点
|
|
171
|
+
hidden?: boolean | (() => boolean);
|
|
110
172
|
// 变量解析参数构造器(用于 variables:resolve 的 contextParams,按属性名归位)。
|
|
111
173
|
// 支持返回 RecordRef 或任意嵌套对象(将被 buildServerContextParams 扁平化,例如 { record: RecordRef } -> 'view.record')。
|
|
112
174
|
buildVariablesParams?: (
|
|
@@ -142,6 +204,10 @@ export interface PropertyOptions {
|
|
|
142
204
|
// - boolean: true 表示整个顶层变量交给服务端;false 表示仅前端解析
|
|
143
205
|
// - function: 根据子路径决定是否交给服务端(子路径示例:'record.roles[0].name'、'id'、'')
|
|
144
206
|
resolveOnServer?: boolean | ((subPath: string) => boolean);
|
|
207
|
+
// 优化:当需要服务端解析但本属性在 buildVariablesParams 返回空时,是否跳过调用服务端。
|
|
208
|
+
// - 典型场景:formValues / currentObject 仅在“已选关联值”存在时才需要服务端;否则没有必要请求。
|
|
209
|
+
// - 默认 false:保持兼容,其他变量即使没有 contextParams 也可选择调用服务端。
|
|
210
|
+
serverOnlyWhenContextParams?: boolean;
|
|
145
211
|
}
|
|
146
212
|
|
|
147
213
|
type RouteOptions = {
|
|
@@ -658,12 +724,13 @@ export class FlowContext {
|
|
|
658
724
|
|
|
659
725
|
let node: MetaTreeNode;
|
|
660
726
|
|
|
661
|
-
//
|
|
662
|
-
const
|
|
663
|
-
if (!m) return { disabled: false };
|
|
727
|
+
// 计算禁用/隐藏状态与原因的帮助函数
|
|
728
|
+
const computeStateFromMeta = (m: PropertyMeta): { disabled: boolean; reason?: string; hidden: boolean } => {
|
|
729
|
+
if (!m) return { disabled: false, hidden: false };
|
|
664
730
|
const disabledVal = typeof m.disabled === 'function' ? m.disabled() : m.disabled;
|
|
665
731
|
const reason = typeof m.disabledReason === 'function' ? m.disabledReason() : m.disabledReason;
|
|
666
|
-
|
|
732
|
+
const hiddenVal = typeof m.hidden === 'function' ? m.hidden() : m.hidden;
|
|
733
|
+
return { disabled: !!disabledVal, reason, hidden: !!hiddenVal };
|
|
667
734
|
};
|
|
668
735
|
|
|
669
736
|
if (typeof metaOrFactory === 'function') {
|
|
@@ -674,18 +741,24 @@ export class FlowContext {
|
|
|
674
741
|
title: metaOrFactory.title || initialTitle, // 初始使用 name 作为 title
|
|
675
742
|
type: 'object', // 初始类型
|
|
676
743
|
interface: undefined,
|
|
744
|
+
options: undefined,
|
|
677
745
|
uiSchema: undefined,
|
|
678
746
|
paths,
|
|
679
747
|
parentTitles: parentTitles.length > 0 ? parentTitles : undefined,
|
|
680
748
|
disabled: () => {
|
|
681
749
|
const maybe = metaOrFactory();
|
|
682
750
|
if (maybe && typeof maybe['then'] === 'function') return false;
|
|
683
|
-
return
|
|
751
|
+
return computeStateFromMeta(maybe as PropertyMeta).disabled;
|
|
684
752
|
},
|
|
685
753
|
disabledReason: () => {
|
|
686
754
|
const maybe = metaOrFactory();
|
|
687
755
|
if (maybe && typeof maybe['then'] === 'function') return undefined;
|
|
688
|
-
return
|
|
756
|
+
return computeStateFromMeta(maybe as PropertyMeta).reason;
|
|
757
|
+
},
|
|
758
|
+
hidden: () => {
|
|
759
|
+
const maybe = metaOrFactory();
|
|
760
|
+
if (maybe && typeof maybe['then'] === 'function') return false;
|
|
761
|
+
return computeStateFromMeta(maybe as PropertyMeta).hidden;
|
|
689
762
|
},
|
|
690
763
|
// 注意:即便 hasChildren === false,也只是“没有子节点”的 UI 提示;
|
|
691
764
|
// 节点自身依然通过 meta 工厂保持惰性特性(需要时可解析出 title/type 等)。
|
|
@@ -700,6 +773,7 @@ export class FlowContext {
|
|
|
700
773
|
node.title = finalTitle;
|
|
701
774
|
node.type = meta?.type;
|
|
702
775
|
node.interface = meta?.interface;
|
|
776
|
+
node.options = meta?.options;
|
|
703
777
|
node.uiSchema = meta?.uiSchema;
|
|
704
778
|
// parentTitles 保持不变,因为它不包含自身 title
|
|
705
779
|
|
|
@@ -726,17 +800,19 @@ export class FlowContext {
|
|
|
726
800
|
} else {
|
|
727
801
|
// 同步 meta:直接创建节点
|
|
728
802
|
const nodeTitle = metaOrFactory.title;
|
|
729
|
-
const { disabled, reason } =
|
|
803
|
+
const { disabled, reason, hidden } = computeStateFromMeta(metaOrFactory);
|
|
730
804
|
node = {
|
|
731
805
|
name,
|
|
732
806
|
title: nodeTitle,
|
|
733
807
|
type: metaOrFactory.type,
|
|
734
808
|
interface: metaOrFactory.interface,
|
|
809
|
+
options: metaOrFactory.options,
|
|
735
810
|
uiSchema: metaOrFactory.uiSchema,
|
|
736
811
|
paths,
|
|
737
812
|
parentTitles: parentTitles.length > 0 ? parentTitles : undefined,
|
|
738
813
|
disabled,
|
|
739
814
|
disabledReason: reason,
|
|
815
|
+
hidden,
|
|
740
816
|
children: metaOrFactory.properties
|
|
741
817
|
? this.#createChildNodes(metaOrFactory.properties, paths, [...parentTitles, nodeTitle], metaOrFactory)
|
|
742
818
|
: undefined,
|
|
@@ -890,33 +966,86 @@ export class FlowContext {
|
|
|
890
966
|
}
|
|
891
967
|
return this._findPropertyInDelegates(this._delegates, key);
|
|
892
968
|
}
|
|
893
|
-
}
|
|
894
969
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
970
|
+
/**
|
|
971
|
+
* 获取当前上下文可用的顶层 API 信息(主要用于编辑器补全/工具)。
|
|
972
|
+
*
|
|
973
|
+
* 注意:
|
|
974
|
+
* - 目前返回值以“尽量可用”为目标,允许不完整。
|
|
975
|
+
* - 该方法不会展开变量 meta(变量结构应由 `getPropertyMetaTree()`/VariableInput 等机制负责)。
|
|
976
|
+
*/
|
|
977
|
+
async getApiInfos(options: { version?: string } = {}): Promise<Record<string, any>> {
|
|
978
|
+
const version = (options as any)?.version || ('v1' as any);
|
|
979
|
+
const modelClass = getModelClassName(this as any);
|
|
980
|
+
const Ctor =
|
|
981
|
+
RunJSContextRegistry.resolve(version as any, modelClass) || RunJSContextRegistry.resolve(version as any, '*');
|
|
982
|
+
const locale = (this as any)?.api?.auth?.locale || (this as any)?.i18n?.language || (this as any)?.locale;
|
|
983
|
+
|
|
984
|
+
let doc: any = {};
|
|
985
|
+
try {
|
|
986
|
+
if ((Ctor as any)?.getDoc?.length) doc = (Ctor as any).getDoc(locale) || {};
|
|
987
|
+
else doc = (Ctor as any)?.getDoc?.() || {};
|
|
988
|
+
} catch (_) {
|
|
989
|
+
doc = {};
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
const isPrivateKey = (key: string) => typeof key === 'string' && key.startsWith('_');
|
|
993
|
+
const out: Record<string, any> = {};
|
|
994
|
+
const visited = new WeakSet<any>();
|
|
995
|
+
|
|
996
|
+
const walk = (ctx: any) => {
|
|
997
|
+
if (!ctx || visited.has(ctx)) return;
|
|
998
|
+
visited.add(ctx);
|
|
999
|
+
|
|
1000
|
+
try {
|
|
1001
|
+
for (const key of Object.keys(ctx._props || {})) {
|
|
1002
|
+
if (isPrivateKey(key)) continue;
|
|
1003
|
+
if (typeof out[key] === 'undefined') out[key] = { type: 'property' };
|
|
911
1004
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1005
|
+
} catch (_) {
|
|
1006
|
+
// ignore
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
try {
|
|
1010
|
+
for (const key of Object.keys(ctx._methods || {})) {
|
|
1011
|
+
if (isPrivateKey(key)) continue;
|
|
1012
|
+
if (typeof out[key] === 'undefined') out[key] = { type: 'function' };
|
|
917
1013
|
}
|
|
918
|
-
}
|
|
919
|
-
|
|
1014
|
+
} catch (_) {
|
|
1015
|
+
// ignore
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
try {
|
|
1019
|
+
const delegates = Array.isArray(ctx._delegates) ? ctx._delegates : [];
|
|
1020
|
+
for (const d of delegates) walk(d);
|
|
1021
|
+
} catch (_) {
|
|
1022
|
+
// ignore
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
walk(this);
|
|
1027
|
+
|
|
1028
|
+
return {
|
|
1029
|
+
...out,
|
|
1030
|
+
...(doc?.properties || {}),
|
|
1031
|
+
...(doc?.methods || {}),
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* 变量结构信息(保留给编辑器/工具使用)。
|
|
1037
|
+
* 当前实现为保底空对象,避免 RunJS doc 中补全到该方法时调用报错。
|
|
1038
|
+
*/
|
|
1039
|
+
async getVarInfos(_options: { path?: string | string[]; maxDepth?: number } = {}): Promise<Record<string, any>> {
|
|
1040
|
+
return {};
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* 运行时环境信息(保留给编辑器/工具使用)。
|
|
1045
|
+
* 当前实现为保底空对象,避免 RunJS doc 中补全到该方法时调用报错。
|
|
1046
|
+
*/
|
|
1047
|
+
async getEnvInfos(): Promise<Record<string, any>> {
|
|
1048
|
+
return {};
|
|
920
1049
|
}
|
|
921
1050
|
}
|
|
922
1051
|
|
|
@@ -924,14 +1053,16 @@ class BaseFlowEngineContext extends FlowContext {
|
|
|
924
1053
|
declare router: Router;
|
|
925
1054
|
declare dataSourceManager: DataSourceManager;
|
|
926
1055
|
declare requireAsync: (url: string) => Promise<any>;
|
|
927
|
-
declare
|
|
1056
|
+
declare importAsync: (url: string) => Promise<any>;
|
|
1057
|
+
declare createJSRunner: (options?: JSRunnerOptions) => Promise<JSRunner>;
|
|
1058
|
+
declare pageInfo: { version?: 'v1' | 'v2' };
|
|
928
1059
|
/**
|
|
929
1060
|
* @deprecated use `resolveJsonTemplate` instead
|
|
930
1061
|
*/
|
|
931
1062
|
declare renderJson: (template: JSONValue) => Promise<any>;
|
|
932
1063
|
declare resolveJsonTemplate: (template: JSONValue) => Promise<any>;
|
|
1064
|
+
declare getVar: (path: string) => Promise<any>;
|
|
933
1065
|
declare runjs: (code: string, variables?: Record<string, any>, options?: JSRunnerOptions) => Promise<any>;
|
|
934
|
-
declare copyToClipboard: (text: string) => Promise<void>;
|
|
935
1066
|
declare getAction: <TModel extends FlowModel = FlowModel, TCtx extends FlowContext = FlowContext>(
|
|
936
1067
|
name: string,
|
|
937
1068
|
) => ActionDefinition<TModel, TCtx> | undefined;
|
|
@@ -955,6 +1086,25 @@ class BaseFlowEngineContext extends FlowContext {
|
|
|
955
1086
|
declare location: Location;
|
|
956
1087
|
declare sql: FlowSQLRepository;
|
|
957
1088
|
declare logger: pino.Logger;
|
|
1089
|
+
|
|
1090
|
+
constructor() {
|
|
1091
|
+
super();
|
|
1092
|
+
this.defineMethod(
|
|
1093
|
+
'runjs',
|
|
1094
|
+
async function (code: string, variables?: Record<string, any>, options?: JSRunnerOptions) {
|
|
1095
|
+
const { preprocessTemplates, ...runnerOptions } = options || {};
|
|
1096
|
+
const mergedGlobals = { ...(runnerOptions?.globals || {}), ...(variables || {}) };
|
|
1097
|
+
const runner = await this.createJSRunner({
|
|
1098
|
+
...(runnerOptions || {}),
|
|
1099
|
+
globals: mergedGlobals,
|
|
1100
|
+
});
|
|
1101
|
+
// Enable by default; use `preprocessTemplates: false` to explicitly disable.
|
|
1102
|
+
const shouldPreprocessTemplates = preprocessTemplates !== false;
|
|
1103
|
+
const jsCode = await prepareRunJsCode(String(code ?? ''), { preprocessTemplates: shouldPreprocessTemplates });
|
|
1104
|
+
return runner.run(jsCode);
|
|
1105
|
+
},
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
958
1108
|
}
|
|
959
1109
|
|
|
960
1110
|
class BaseFlowModelContext extends BaseFlowEngineContext {
|
|
@@ -994,7 +1144,8 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
994
1144
|
value: this.engine,
|
|
995
1145
|
});
|
|
996
1146
|
this.defineProperty('sql', {
|
|
997
|
-
get: () => new FlowSQLRepository(
|
|
1147
|
+
get: (ctx) => new FlowSQLRepository(ctx),
|
|
1148
|
+
cache: false,
|
|
998
1149
|
});
|
|
999
1150
|
this.defineProperty('dataSourceManager', {
|
|
1000
1151
|
value: dataSourceManager,
|
|
@@ -1003,14 +1154,6 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1003
1154
|
this.defineMethod('t', (keyOrTemplate: string, options?: any) => {
|
|
1004
1155
|
return i18n.translate(keyOrTemplate, options);
|
|
1005
1156
|
});
|
|
1006
|
-
this.defineMethod('runjs', async (code, variables, options?: JSRunnerOptions) => {
|
|
1007
|
-
const mergedGlobals = { ...(options?.globals || {}), ...(variables || {}) };
|
|
1008
|
-
const runner = this.createJSRunner({
|
|
1009
|
-
...(options || {}),
|
|
1010
|
-
globals: mergedGlobals,
|
|
1011
|
-
});
|
|
1012
|
-
return runner.run(code);
|
|
1013
|
-
});
|
|
1014
1157
|
this.defineMethod('renderJson', function (template: any) {
|
|
1015
1158
|
return this.resolveJsonTemplate(template);
|
|
1016
1159
|
});
|
|
@@ -1046,6 +1189,22 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1046
1189
|
const needServer = Object.keys(serverVarPaths).length > 0;
|
|
1047
1190
|
let serverResolved = template;
|
|
1048
1191
|
if (needServer) {
|
|
1192
|
+
const inferRecordRefWithMeta = (ctx: any): RecordRef | undefined => {
|
|
1193
|
+
const ref = inferRecordRef(ctx as any);
|
|
1194
|
+
if (ref) return ref as RecordRef;
|
|
1195
|
+
try {
|
|
1196
|
+
const tk = ctx?.resource?.getMeta?.('currentFilterByTk');
|
|
1197
|
+
if (typeof tk === 'undefined' || tk === null) return undefined;
|
|
1198
|
+
const collection =
|
|
1199
|
+
ctx?.collection?.name || ctx?.resource?.getResourceName?.()?.split?.('.')?.slice?.(-1)?.[0];
|
|
1200
|
+
if (!collection) return undefined;
|
|
1201
|
+
const dataSourceKey = ctx?.collection?.dataSourceKey || ctx?.resource?.getDataSourceKey?.();
|
|
1202
|
+
return { collection, dataSourceKey, filterByTk: tk } as RecordRef;
|
|
1203
|
+
} catch (_) {
|
|
1204
|
+
return undefined;
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1049
1208
|
const collectFromMeta = async (): Promise<Record<string, any>> => {
|
|
1050
1209
|
const out: Record<string, any> = {};
|
|
1051
1210
|
try {
|
|
@@ -1085,11 +1244,77 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1085
1244
|
};
|
|
1086
1245
|
|
|
1087
1246
|
const inputFromMeta = await collectFromMeta();
|
|
1088
|
-
const autoInput = { ...inputFromMeta }
|
|
1247
|
+
const autoInput = { ...inputFromMeta } as Record<string, any>;
|
|
1248
|
+
|
|
1249
|
+
// Special-case: formValues
|
|
1250
|
+
// If server needs to resolve some formValues paths but meta params only cover association anchors
|
|
1251
|
+
// (e.g. formValues.customer) and some top-level paths are missing (e.g. formValues.status),
|
|
1252
|
+
// inject a top-level record anchor (formValues -> { collection, filterByTk, fields/appends }) so server can fetch DB values.
|
|
1253
|
+
// This anchor MUST be selective (fields/appends derived from serverVarPaths['formValues']) to avoid server overriding
|
|
1254
|
+
// client-only values for configured form fields in the same template.
|
|
1255
|
+
try {
|
|
1256
|
+
const varName = 'formValues';
|
|
1257
|
+
const neededPaths = serverVarPaths[varName] || [];
|
|
1258
|
+
if (neededPaths.length) {
|
|
1259
|
+
const requiredTop = new Set<string>();
|
|
1260
|
+
for (const p of neededPaths) {
|
|
1261
|
+
const top = topLevelOf(p);
|
|
1262
|
+
if (top) requiredTop.add(top);
|
|
1263
|
+
}
|
|
1264
|
+
const metaOut = inputFromMeta?.[varName];
|
|
1265
|
+
const builtTop = new Set<string>();
|
|
1266
|
+
if (metaOut && typeof metaOut === 'object' && !Array.isArray(metaOut) && !isRecordRefLike(metaOut)) {
|
|
1267
|
+
Object.keys(metaOut).forEach((k) => builtTop.add(k));
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
const missing = [...requiredTop].filter((k) => !builtTop.has(k));
|
|
1271
|
+
if (missing.length) {
|
|
1272
|
+
const ref = inferRecordRefWithMeta(this);
|
|
1273
|
+
if (ref) {
|
|
1274
|
+
const { generatedFields, generatedAppends } = inferSelectsFromUsage(neededPaths);
|
|
1275
|
+
const recordRef: RecordRef = {
|
|
1276
|
+
...ref,
|
|
1277
|
+
fields: generatedFields,
|
|
1278
|
+
appends: generatedAppends,
|
|
1279
|
+
};
|
|
1280
|
+
|
|
1281
|
+
// Preserve existing association anchors by lifting them to dotted keys before overwriting formValues
|
|
1282
|
+
const existing = autoInput[varName];
|
|
1283
|
+
if (
|
|
1284
|
+
existing &&
|
|
1285
|
+
typeof existing === 'object' &&
|
|
1286
|
+
!Array.isArray(existing) &&
|
|
1287
|
+
!isRecordRefLike(existing)
|
|
1288
|
+
) {
|
|
1289
|
+
for (const [k, v] of Object.entries(existing)) {
|
|
1290
|
+
autoInput[`${varName}.${k}`] = v;
|
|
1291
|
+
}
|
|
1292
|
+
delete autoInput[varName];
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
autoInput[varName] = recordRef;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
} catch (_) {
|
|
1300
|
+
// ignore
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1089
1303
|
const autoContextParams = Object.keys(autoInput).length
|
|
1090
1304
|
? _buildServerContextParams(this, autoInput)
|
|
1091
1305
|
: undefined;
|
|
1092
1306
|
|
|
1307
|
+
// 优化:若所有需要服务端解析的变量都声明了 “仅当有 contextParams 时才请求服务端”,
|
|
1308
|
+
// 且本次未能构建出任何 contextParams,则跳过服务端请求,回退到前端解析。
|
|
1309
|
+
if (!autoContextParams) {
|
|
1310
|
+
const keys = Object.keys(serverVarPaths);
|
|
1311
|
+
const allOptional =
|
|
1312
|
+
keys.length > 0 && keys.every((k) => this.getPropertyOptions(k)?.serverOnlyWhenContextParams);
|
|
1313
|
+
if (allOptional) {
|
|
1314
|
+
return resolveExpressions(template, this);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1093
1318
|
if (this.api) {
|
|
1094
1319
|
try {
|
|
1095
1320
|
serverResolved = await enqueueVariablesResolve(this as FlowRuntimeContext<FlowModel>, {
|
|
@@ -1105,6 +1330,23 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1105
1330
|
|
|
1106
1331
|
return resolveExpressions(serverResolved, this);
|
|
1107
1332
|
});
|
|
1333
|
+
|
|
1334
|
+
// Helper: resolve a single ctx expression value via resolveJsonTemplate behavior.
|
|
1335
|
+
// Example: await ctx.getVar('ctx.record.id')
|
|
1336
|
+
this.defineMethod(
|
|
1337
|
+
'getVar',
|
|
1338
|
+
async function (this: BaseFlowEngineContext, varPath: string) {
|
|
1339
|
+
const raw = typeof varPath === 'string' ? varPath : String(varPath ?? '');
|
|
1340
|
+
const s = raw.trim();
|
|
1341
|
+
if (!s) return undefined;
|
|
1342
|
+
// Preferred input: 'ctx.xxx.yyy' (expression), consistent with envs.getVar outputs.
|
|
1343
|
+
if (s !== 'ctx' && !s.startsWith('ctx.')) {
|
|
1344
|
+
throw new Error(`ctx.getVar(path) expects an expression starting with "ctx.", got: "${s}"`);
|
|
1345
|
+
}
|
|
1346
|
+
return this.resolveJsonTemplate(`{{ ${s} }}` as any);
|
|
1347
|
+
},
|
|
1348
|
+
'Resolve a ctx expression value by path (expression starts with "ctx.").',
|
|
1349
|
+
);
|
|
1108
1350
|
this.defineProperty('requirejs', {
|
|
1109
1351
|
get: () => this.app?.requirejs?.requirejs,
|
|
1110
1352
|
});
|
|
@@ -1186,7 +1428,8 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1186
1428
|
user: this.user,
|
|
1187
1429
|
}),
|
|
1188
1430
|
});
|
|
1189
|
-
this.defineMethod('loadCSS', async (
|
|
1431
|
+
this.defineMethod('loadCSS', async (href: string) => {
|
|
1432
|
+
const url = resolveModuleUrl(href);
|
|
1190
1433
|
return new Promise((resolve, reject) => {
|
|
1191
1434
|
// Check if CSS is already loaded
|
|
1192
1435
|
const existingLink = document.querySelector(`link[href="${url}"]`);
|
|
@@ -1204,64 +1447,34 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1204
1447
|
});
|
|
1205
1448
|
});
|
|
1206
1449
|
this.defineMethod('requireAsync', async (url: string) => {
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
reject(new Error('requirejs is not available'));
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
this.requirejs(
|
|
1213
|
-
[url],
|
|
1214
|
-
(...args: any[]) => {
|
|
1215
|
-
resolve(args[0]);
|
|
1216
|
-
},
|
|
1217
|
-
reject,
|
|
1218
|
-
);
|
|
1219
|
-
});
|
|
1450
|
+
const u = resolveModuleUrl(url, { raw: true });
|
|
1451
|
+
return await runjsRequireAsync(this.requirejs, u);
|
|
1220
1452
|
});
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
},
|
|
1232
|
-
});
|
|
1453
|
+
// 动态按 URL 加载 ESM 模块
|
|
1454
|
+
// - 使用 Vite / Webpack ignore 注释,避免被预打包或重写
|
|
1455
|
+
// - 返回模块命名空间对象(包含 default 与命名导出)
|
|
1456
|
+
this.defineMethod('importAsync', async function (this: any, url: string) {
|
|
1457
|
+
// 判断是否为 CSS 文件(支持 example.css?v=123 等形式)
|
|
1458
|
+
if (isCssFile(url)) {
|
|
1459
|
+
return this.loadCSS(url);
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
return await runjsImportModule(this, url, { importer: runjsImportAsync });
|
|
1233
1463
|
});
|
|
1234
|
-
|
|
1235
|
-
this.defineMethod('copyToClipboard', async (text: string) => {
|
|
1236
|
-
const content = String(text ?? '');
|
|
1464
|
+
this.defineMethod('createJSRunner', async function (options?: JSRunnerOptions) {
|
|
1237
1465
|
try {
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
} catch (e) {
|
|
1243
|
-
// 忽略,尝试降级方案
|
|
1466
|
+
const mod: any = await import('./runjs-context/setup');
|
|
1467
|
+
if (typeof mod?.setupRunJSContexts === 'function') await mod.setupRunJSContexts();
|
|
1468
|
+
} catch (_) {
|
|
1469
|
+
// ignore if setup is not available
|
|
1244
1470
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
ta.style.position = 'fixed';
|
|
1253
|
-
ta.style.top = '-9999px';
|
|
1254
|
-
document.body.appendChild(ta);
|
|
1255
|
-
ta.focus();
|
|
1256
|
-
ta.select();
|
|
1257
|
-
const ok = document.execCommand('copy');
|
|
1258
|
-
document.body.removeChild(ta);
|
|
1259
|
-
if (ok) resolve();
|
|
1260
|
-
else reject(new Error('execCommand copy failed'));
|
|
1261
|
-
} catch (err) {
|
|
1262
|
-
reject(err);
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1471
|
+
const version = options?.version || 'v1';
|
|
1472
|
+
const modelClass = getModelClassName(this);
|
|
1473
|
+
const Ctor: new (delegate: any) => any = RunJSContextRegistry.resolve(version, modelClass) || FlowRunJSContext;
|
|
1474
|
+
const runCtx = new Ctor(this);
|
|
1475
|
+
const globals: Record<string, any> = { ctx: runCtx, ...(options?.globals || {}) };
|
|
1476
|
+
const { timeoutMs } = options || {};
|
|
1477
|
+
return new JSRunner({ globals, timeoutMs });
|
|
1265
1478
|
});
|
|
1266
1479
|
// Helper: build server contextParams for variables:resolve
|
|
1267
1480
|
this.defineMethod('buildServerContextParams', function (this: BaseFlowEngineContext, input?: any) {
|
|
@@ -1332,7 +1545,8 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1332
1545
|
'runAction',
|
|
1333
1546
|
async function (this: BaseFlowEngineContext, actionName: string, params?: Record<string, any>) {
|
|
1334
1547
|
const def = this.engine.getAction<FlowModel, FlowEngineContext>(actionName);
|
|
1335
|
-
|
|
1548
|
+
// 使用“临时作用域”上下文,避免将临时定义污染到引擎级上下文,并在创建时应用定义
|
|
1549
|
+
const ctx = await createEphemeralContext(this as unknown as FlowEngineContext, def);
|
|
1336
1550
|
if (!def) {
|
|
1337
1551
|
throw new Error(`Action '${actionName}' not found.`);
|
|
1338
1552
|
}
|
|
@@ -1346,7 +1560,7 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1346
1560
|
}
|
|
1347
1561
|
if (!useRawParams) {
|
|
1348
1562
|
// 先服务端解析,再前端补齐
|
|
1349
|
-
combinedParams = await
|
|
1563
|
+
combinedParams = await ctx.resolveJsonTemplate(combinedParams);
|
|
1350
1564
|
}
|
|
1351
1565
|
|
|
1352
1566
|
if (!def.handler) {
|
|
@@ -1369,12 +1583,25 @@ export class FlowEngineContext extends BaseFlowEngineContext {
|
|
|
1369
1583
|
context: this.createProxy(),
|
|
1370
1584
|
});
|
|
1371
1585
|
});
|
|
1586
|
+
// Provide useResource in base engine context so RunJS can call it directly
|
|
1587
|
+
this.defineMethod(
|
|
1588
|
+
'useResource',
|
|
1589
|
+
function (
|
|
1590
|
+
this: BaseFlowEngineContext,
|
|
1591
|
+
className: 'APIResource' | 'SingleRecordResource' | 'MultiRecordResource' | 'SQLResource',
|
|
1592
|
+
) {
|
|
1593
|
+
if (this.has('resource')) return;
|
|
1594
|
+
this.defineProperty('resource', {
|
|
1595
|
+
get: () => this.createResource(className),
|
|
1596
|
+
});
|
|
1597
|
+
},
|
|
1598
|
+
);
|
|
1372
1599
|
}
|
|
1373
1600
|
}
|
|
1374
1601
|
|
|
1375
1602
|
export class FlowModelContext extends BaseFlowModelContext {
|
|
1376
1603
|
constructor(model: FlowModel) {
|
|
1377
|
-
if (!
|
|
1604
|
+
if (!model || typeof model !== 'object') {
|
|
1378
1605
|
throw new Error('Invalid FlowModel instance');
|
|
1379
1606
|
}
|
|
1380
1607
|
super();
|
|
@@ -1382,13 +1609,6 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1382
1609
|
this.defineMethod('onRefReady', (ref, cb, timeout) => {
|
|
1383
1610
|
this.engine.reactView.onRefReady(ref, cb, timeout);
|
|
1384
1611
|
});
|
|
1385
|
-
this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
|
|
1386
|
-
const runner = this.createJSRunner({
|
|
1387
|
-
globals: variables,
|
|
1388
|
-
version: options?.version,
|
|
1389
|
-
});
|
|
1390
|
-
return runner.run(code);
|
|
1391
|
-
});
|
|
1392
1612
|
this.defineProperty('model', {
|
|
1393
1613
|
value: model,
|
|
1394
1614
|
});
|
|
@@ -1402,12 +1622,22 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1402
1622
|
});
|
|
1403
1623
|
this.defineMethod('openView', async function (uid: string, options) {
|
|
1404
1624
|
const opts = { ...options };
|
|
1405
|
-
|
|
1625
|
+
// NOTE: when custom context is passed, route navigation must be disabled to avoid losing it after refresh.
|
|
1626
|
+
if (opts.defineProperties || opts.defineMethods) {
|
|
1406
1627
|
opts.navigation = false; // 强制不使用路由导航, 避免刷新页面时丢失上下文
|
|
1407
1628
|
}
|
|
1408
1629
|
let model: FlowModel | null = null;
|
|
1409
1630
|
model = await this.engine.loadModel({ uid });
|
|
1410
1631
|
if (!model) {
|
|
1632
|
+
const pickDefined = (src: Record<string, any>, keys: string[]) => {
|
|
1633
|
+
const res: Record<string, any> = {};
|
|
1634
|
+
for (const k of keys) {
|
|
1635
|
+
if (typeof src?.[k] !== 'undefined') {
|
|
1636
|
+
res[k] = src[k];
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
return res;
|
|
1640
|
+
};
|
|
1411
1641
|
model = this.engine.createModel({
|
|
1412
1642
|
uid, // 注意: 新建的 model 应该使用 ${parentModel.uid}-xxx 形式的 uid
|
|
1413
1643
|
use: 'PopupActionModel',
|
|
@@ -1417,23 +1647,16 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1417
1647
|
stepParams: {
|
|
1418
1648
|
popupSettings: {
|
|
1419
1649
|
openView: {
|
|
1420
|
-
|
|
1650
|
+
// 仅在创建时持久化一份默认配置;运行时以本次 opts 为准,避免多个 opener 互相覆盖。
|
|
1651
|
+
...pickDefined(opts, ['dataSourceKey', 'collectionName', 'associationName', 'mode', 'size']),
|
|
1421
1652
|
},
|
|
1422
1653
|
},
|
|
1423
1654
|
},
|
|
1424
1655
|
});
|
|
1425
1656
|
await model.save();
|
|
1426
1657
|
}
|
|
1427
|
-
if (model.getStepParams('popupSettings')?.openView?.dataSourceKey) {
|
|
1428
|
-
model.setStepParams('popupSettings', {
|
|
1429
|
-
openView: {
|
|
1430
|
-
...model.getStepParams('popupSettings')?.openView,
|
|
1431
|
-
..._.pick(opts, ['dataSourceKey', 'collectionName', 'associationName']),
|
|
1432
|
-
},
|
|
1433
|
-
});
|
|
1434
|
-
await model.save();
|
|
1435
|
-
}
|
|
1436
1658
|
|
|
1659
|
+
model.setParent(this.model);
|
|
1437
1660
|
// 路由层级的 viewUid:优先使用 routeViewUid(仅用于路由展示);
|
|
1438
1661
|
// 否则回退到 opts.viewUid;再否则沿用原有规则(若子模型具备弹窗配置则使用子模型 uid,否则使用发起者 uid)。
|
|
1439
1662
|
const viewUid =
|
|
@@ -1456,13 +1679,26 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1456
1679
|
engineCtx: this.engine.context,
|
|
1457
1680
|
};
|
|
1458
1681
|
model.context.defineProperty('view', { value: pendingView });
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1682
|
+
// 默认按 click 打开,但兼容 popupSettings 绑定到其他事件(例如 DuplicateActionModel 监听 openDuplicatePopup)。
|
|
1683
|
+
const popupFlow = model.getFlow?.('popupSettings');
|
|
1684
|
+
const on = (popupFlow as any)?.on;
|
|
1685
|
+
let openEventName = 'click';
|
|
1686
|
+
if (typeof on === 'string' && on) {
|
|
1687
|
+
openEventName = on;
|
|
1688
|
+
} else if (on && typeof on === 'object' && typeof (on as any).eventName === 'string' && (on as any).eventName) {
|
|
1689
|
+
openEventName = (on as any).eventName;
|
|
1690
|
+
}
|
|
1691
|
+
await model.dispatchEvent(
|
|
1692
|
+
openEventName,
|
|
1693
|
+
{
|
|
1694
|
+
// navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
|
|
1695
|
+
// ...this.model?.['getInputArgs']?.(), // 避免部分关系字段信息丢失, 仿照 ClickableCollectionField 做法
|
|
1696
|
+
...opts,
|
|
1697
|
+
},
|
|
1698
|
+
{
|
|
1699
|
+
debounce: true,
|
|
1700
|
+
},
|
|
1701
|
+
);
|
|
1466
1702
|
});
|
|
1467
1703
|
this.defineMethod('getEvents', function (this: BaseFlowModelContext) {
|
|
1468
1704
|
return this.model.getEvents();
|
|
@@ -1477,7 +1713,8 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1477
1713
|
'runAction',
|
|
1478
1714
|
async function (this: BaseFlowModelContext, actionName: string, params?: Record<string, any>) {
|
|
1479
1715
|
const def = this.model.getAction<FlowModel, FlowModelContext>(actionName);
|
|
1480
|
-
|
|
1716
|
+
// 使用“临时作用域”上下文,避免将临时定义污染到模型级上下文,并在创建时应用定义
|
|
1717
|
+
const ctx = await createEphemeralContext(this as unknown as FlowModelContext, def);
|
|
1481
1718
|
if (!def) {
|
|
1482
1719
|
throw new Error(`Action '${actionName}' not found.`);
|
|
1483
1720
|
}
|
|
@@ -1490,7 +1727,7 @@ export class FlowModelContext extends BaseFlowModelContext {
|
|
|
1490
1727
|
useRawParams = await useRawParams(ctx);
|
|
1491
1728
|
}
|
|
1492
1729
|
if (!useRawParams) {
|
|
1493
|
-
combinedParams = await
|
|
1730
|
+
combinedParams = await ctx.resolveJsonTemplate(combinedParams);
|
|
1494
1731
|
}
|
|
1495
1732
|
|
|
1496
1733
|
if (!def.handler) {
|
|
@@ -1507,11 +1744,11 @@ export class FlowForkModelContext extends BaseFlowModelContext {
|
|
|
1507
1744
|
public master: FlowModel,
|
|
1508
1745
|
public fork: ForkFlowModel,
|
|
1509
1746
|
) {
|
|
1510
|
-
if (!
|
|
1747
|
+
if (!master || typeof master !== 'object') {
|
|
1511
1748
|
throw new Error('Invalid FlowModel instance');
|
|
1512
1749
|
}
|
|
1513
1750
|
super();
|
|
1514
|
-
this.addDelegate(
|
|
1751
|
+
this.addDelegate(this.master.context);
|
|
1515
1752
|
this.defineMethod('onRefReady', (ref, cb, timeout) => {
|
|
1516
1753
|
this.engine.reactView.onRefReady(ref, cb, timeout);
|
|
1517
1754
|
});
|
|
@@ -1526,13 +1763,6 @@ export class FlowForkModelContext extends BaseFlowModelContext {
|
|
|
1526
1763
|
return stableRef;
|
|
1527
1764
|
},
|
|
1528
1765
|
});
|
|
1529
|
-
this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
|
|
1530
|
-
const runner = this.createJSRunner({
|
|
1531
|
-
globals: variables,
|
|
1532
|
-
version: options?.version,
|
|
1533
|
-
});
|
|
1534
|
-
return runner.run(code);
|
|
1535
|
-
});
|
|
1536
1766
|
}
|
|
1537
1767
|
}
|
|
1538
1768
|
|
|
@@ -1587,13 +1817,6 @@ export class FlowRuntimeContext<
|
|
|
1587
1817
|
this.defineMethod('onRefReady', (ref, cb, timeout) => {
|
|
1588
1818
|
this.engine.reactView.onRefReady(ref, cb, timeout);
|
|
1589
1819
|
});
|
|
1590
|
-
this.defineMethod('runjs', async (code, variables, options?: { version?: string }) => {
|
|
1591
|
-
const runner = this.createJSRunner({
|
|
1592
|
-
globals: variables,
|
|
1593
|
-
version: options?.version,
|
|
1594
|
-
});
|
|
1595
|
-
return runner.run(code);
|
|
1596
|
-
});
|
|
1597
1820
|
}
|
|
1598
1821
|
|
|
1599
1822
|
protected _getOwnProperty(key: string): any {
|
|
@@ -1641,3 +1864,268 @@ export class FlowRuntimeContext<
|
|
|
1641
1864
|
|
|
1642
1865
|
// 类型别名,方便使用
|
|
1643
1866
|
export type FlowSettingsContext<TModel extends FlowModel = FlowModel> = FlowRuntimeContext<TModel, 'settings'>;
|
|
1867
|
+
|
|
1868
|
+
export type FlowContextDocRef = string | { url: string; title?: string };
|
|
1869
|
+
|
|
1870
|
+
export type FlowDeprecationDoc =
|
|
1871
|
+
| boolean
|
|
1872
|
+
| {
|
|
1873
|
+
message?: string;
|
|
1874
|
+
replacedBy?: string | string[];
|
|
1875
|
+
since?: string;
|
|
1876
|
+
removedIn?: string;
|
|
1877
|
+
ref?: FlowContextDocRef;
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
export type FlowContextDocParam = {
|
|
1881
|
+
name: string;
|
|
1882
|
+
description?: string;
|
|
1883
|
+
type?: string;
|
|
1884
|
+
optional?: boolean;
|
|
1885
|
+
default?: JSONValue;
|
|
1886
|
+
};
|
|
1887
|
+
|
|
1888
|
+
export type FlowContextDocReturn = {
|
|
1889
|
+
description?: string;
|
|
1890
|
+
type?: string;
|
|
1891
|
+
};
|
|
1892
|
+
|
|
1893
|
+
export type RunJSDocCompletionDoc = {
|
|
1894
|
+
insertText?: string;
|
|
1895
|
+
};
|
|
1896
|
+
|
|
1897
|
+
export type RunJSDocHiddenDoc = boolean | ((ctx: any) => boolean | Promise<boolean>);
|
|
1898
|
+
|
|
1899
|
+
// `hidden` is the single visibility entrypoint for RunJSDoc property docs:
|
|
1900
|
+
// - boolean: hide the whole node and its subtree
|
|
1901
|
+
// - string[]: hide specific subpaths under the node (relative dot-paths)
|
|
1902
|
+
export type RunJSDocHiddenOrPathsDoc =
|
|
1903
|
+
| boolean
|
|
1904
|
+
| string[]
|
|
1905
|
+
| ((ctx: any) => boolean | string[] | Promise<boolean | string[]>);
|
|
1906
|
+
|
|
1907
|
+
export type RunJSDocPropertyDoc =
|
|
1908
|
+
| string
|
|
1909
|
+
| {
|
|
1910
|
+
description?: string;
|
|
1911
|
+
detail?: string;
|
|
1912
|
+
type?: string;
|
|
1913
|
+
examples?: string[];
|
|
1914
|
+
completion?: RunJSDocCompletionDoc;
|
|
1915
|
+
ref?: FlowContextDocRef;
|
|
1916
|
+
deprecated?: FlowDeprecationDoc;
|
|
1917
|
+
params?: FlowContextDocParam[];
|
|
1918
|
+
returns?: FlowContextDocReturn;
|
|
1919
|
+
properties?: Record<string, RunJSDocPropertyDoc>;
|
|
1920
|
+
hidden?: RunJSDocHiddenOrPathsDoc;
|
|
1921
|
+
disabled?: boolean | ((ctx: any) => boolean | Promise<boolean>);
|
|
1922
|
+
disabledReason?: string | ((ctx: any) => string | undefined | Promise<string | undefined>);
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1925
|
+
export type RunJSDocMethodDoc =
|
|
1926
|
+
| string
|
|
1927
|
+
| {
|
|
1928
|
+
description?: string;
|
|
1929
|
+
detail?: string;
|
|
1930
|
+
examples?: string[];
|
|
1931
|
+
completion?: RunJSDocCompletionDoc;
|
|
1932
|
+
ref?: FlowContextDocRef;
|
|
1933
|
+
deprecated?: FlowDeprecationDoc;
|
|
1934
|
+
params?: FlowContextDocParam[];
|
|
1935
|
+
returns?: FlowContextDocReturn;
|
|
1936
|
+
hidden?: RunJSDocHiddenDoc;
|
|
1937
|
+
disabled?: boolean | ((ctx: any) => boolean | Promise<boolean>);
|
|
1938
|
+
disabledReason?: string | ((ctx: any) => string | undefined | Promise<string | undefined>);
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
export type RunJSDocMeta = {
|
|
1942
|
+
label?: string;
|
|
1943
|
+
properties?: Record<string, RunJSDocPropertyDoc>;
|
|
1944
|
+
methods?: Record<string, RunJSDocMethodDoc>;
|
|
1945
|
+
snippets?: Record<string, any>;
|
|
1946
|
+
};
|
|
1947
|
+
|
|
1948
|
+
const __runjsClassDefaultMeta = new WeakMap<Function, RunJSDocMeta>();
|
|
1949
|
+
const __runjsClassLocaleMeta = new WeakMap<Function, Map<string, RunJSDocMeta>>();
|
|
1950
|
+
const __runjsDocCache = new WeakMap<Function, Map<string, RunJSDocMeta>>();
|
|
1951
|
+
|
|
1952
|
+
function __runjsDeepMerge(base: any, patch: any) {
|
|
1953
|
+
if (patch === null) return undefined;
|
|
1954
|
+
if (Array.isArray(base) || Array.isArray(patch) || typeof base !== 'object' || typeof patch !== 'object') {
|
|
1955
|
+
return patch ?? base;
|
|
1956
|
+
}
|
|
1957
|
+
const out: any = { ...base };
|
|
1958
|
+
for (const k of Object.keys(patch)) {
|
|
1959
|
+
const v = __runjsDeepMerge(base?.[k], patch[k]);
|
|
1960
|
+
if (typeof v === 'undefined') delete out[k];
|
|
1961
|
+
else out[k] = v;
|
|
1962
|
+
}
|
|
1963
|
+
return out;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
export class FlowRunJSContext extends FlowContext {
|
|
1967
|
+
constructor(delegate: FlowContext) {
|
|
1968
|
+
super();
|
|
1969
|
+
this.addDelegate(delegate);
|
|
1970
|
+
this.defineProperty('React', { value: React });
|
|
1971
|
+
this.defineProperty('antd', { value: antd });
|
|
1972
|
+
this.defineProperty('dayjs', { value: dayjs });
|
|
1973
|
+
// 为 JS 运行时代码提供带有 antd/App/ConfigProvider 包裹的 React 根
|
|
1974
|
+
// 保持与 ReactDOMClient 接口一致,优先覆盖 createRoot,其余方法透传
|
|
1975
|
+
const ReactDOMShim: any = {
|
|
1976
|
+
...ReactDOMClient,
|
|
1977
|
+
createRoot: (container: Element | DocumentFragment, options?: any) => {
|
|
1978
|
+
// 兼容 ElementProxy:若传入的是代理对象,取其底层原生元素
|
|
1979
|
+
const realContainer: any = (container as any)?.__el || container;
|
|
1980
|
+
// 使用引擎自带的 reactView.createRoot,以继承应用内的 ConfigProvider/App 上下文与主题
|
|
1981
|
+
return this.engine.reactView.createRoot(realContainer as HTMLElement, options);
|
|
1982
|
+
},
|
|
1983
|
+
};
|
|
1984
|
+
ReactDOMShim.__nbRunjsInternalShim = true;
|
|
1985
|
+
this.defineProperty('ReactDOM', { value: ReactDOMShim });
|
|
1986
|
+
|
|
1987
|
+
setupRunJSLibs(this);
|
|
1988
|
+
|
|
1989
|
+
// Convenience: ctx.render(<App />[, container])
|
|
1990
|
+
// - container defaults to ctx.element if available
|
|
1991
|
+
// - internally uses engine.reactView.createRoot to inherit app context
|
|
1992
|
+
// - caches root per container via global WeakMap
|
|
1993
|
+
this.defineMethod(
|
|
1994
|
+
'render',
|
|
1995
|
+
function (
|
|
1996
|
+
this: any,
|
|
1997
|
+
vnode: React.ReactElement | Node | DocumentFragment | string,
|
|
1998
|
+
container?: Element | DocumentFragment,
|
|
1999
|
+
) {
|
|
2000
|
+
const el = (container as any) || (this.element as any);
|
|
2001
|
+
if (!el) throw new Error('ctx.render: container not provided and ctx.element is not available');
|
|
2002
|
+
const containerEl: any = (el as any)?.__el || el; // unwrap ElementProxy
|
|
2003
|
+
const globalRef: any = globalThis as any;
|
|
2004
|
+
globalRef.__nbRunjsRoots = globalRef.__nbRunjsRoots || new WeakMap<any, any>();
|
|
2005
|
+
const rootMap: WeakMap<any, any> = globalRef.__nbRunjsRoots;
|
|
2006
|
+
|
|
2007
|
+
const disposeEntry = (entry: any) => {
|
|
2008
|
+
if (!entry) return;
|
|
2009
|
+
if (entry.disposeTheme && typeof entry.disposeTheme === 'function') {
|
|
2010
|
+
try {
|
|
2011
|
+
entry.disposeTheme();
|
|
2012
|
+
} catch (_) {
|
|
2013
|
+
// ignore
|
|
2014
|
+
}
|
|
2015
|
+
entry.disposeTheme = undefined;
|
|
2016
|
+
}
|
|
2017
|
+
const root = entry.root || entry;
|
|
2018
|
+
if (root && typeof root.unmount === 'function') {
|
|
2019
|
+
try {
|
|
2020
|
+
root.unmount();
|
|
2021
|
+
} catch (_) {
|
|
2022
|
+
// ignore
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
|
|
2027
|
+
const unmountContainerRoot = () => {
|
|
2028
|
+
const existing = rootMap.get(containerEl);
|
|
2029
|
+
if (existing) {
|
|
2030
|
+
disposeEntry(existing);
|
|
2031
|
+
rootMap.delete(containerEl);
|
|
2032
|
+
}
|
|
2033
|
+
};
|
|
2034
|
+
|
|
2035
|
+
// If vnode is string (HTML), unmount react root and set sanitized HTML
|
|
2036
|
+
if (typeof vnode === 'string') {
|
|
2037
|
+
unmountContainerRoot();
|
|
2038
|
+
const proxy: any = new ElementProxy(containerEl);
|
|
2039
|
+
proxy.innerHTML = String(vnode ?? '');
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
// If vnode is a DOM Node or DocumentFragment, unmount and replace content
|
|
2044
|
+
if (
|
|
2045
|
+
vnode &&
|
|
2046
|
+
(vnode as any).nodeType &&
|
|
2047
|
+
((vnode as any).nodeType === 1 || (vnode as any).nodeType === 3 || (vnode as any).nodeType === 11)
|
|
2048
|
+
) {
|
|
2049
|
+
unmountContainerRoot();
|
|
2050
|
+
while (containerEl.firstChild) containerEl.removeChild(containerEl.firstChild);
|
|
2051
|
+
containerEl.appendChild(vnode as any);
|
|
2052
|
+
return null;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
// 注意:rootMap 是“全局按容器复用”的(key=containerEl)。
|
|
2056
|
+
// 若不同 RunJS ctx 复用同一个 containerEl,且 ReactDOM 实例引用也相同,
|
|
2057
|
+
// 则会复用到旧 entry,进而复用旧 ctx 创建的 autorun(闭包捕获旧 ctx),造成:
|
|
2058
|
+
// 1) 旧 ctx 的 reaction 继续驱动新渲染(跨 ctx 复用风险)
|
|
2059
|
+
// 2) 新 ctx 的主题变化不再触发 rerender
|
|
2060
|
+
// 3) 旧 ctx 被 entry/autorun 间接持有,无法被 GC(内存泄漏)
|
|
2061
|
+
// 因此这里把 ownerKey(当前 ctx)也纳入复用判断;owner 变化时必须重建 entry。
|
|
2062
|
+
const rendererKey = this.ReactDOM;
|
|
2063
|
+
const ownerKey = this;
|
|
2064
|
+
let entry = rootMap.get(containerEl);
|
|
2065
|
+
if (!entry || entry.rendererKey !== rendererKey || entry.ownerKey !== ownerKey) {
|
|
2066
|
+
if (entry) {
|
|
2067
|
+
disposeEntry(entry);
|
|
2068
|
+
rootMap.delete(containerEl);
|
|
2069
|
+
}
|
|
2070
|
+
const root = this.ReactDOM.createRoot(containerEl);
|
|
2071
|
+
entry = { rendererKey, ownerKey, root, disposeTheme: undefined, lastVnode: undefined };
|
|
2072
|
+
rootMap.set(containerEl, entry);
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
return externalReactRender({
|
|
2076
|
+
ctx: this,
|
|
2077
|
+
entry,
|
|
2078
|
+
vnode,
|
|
2079
|
+
containerEl,
|
|
2080
|
+
rootMap,
|
|
2081
|
+
unmountContainerRoot,
|
|
2082
|
+
internalReact: React,
|
|
2083
|
+
internalAntd: antd,
|
|
2084
|
+
});
|
|
2085
|
+
},
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
static define(meta: RunJSDocMeta, options?: { locale?: string }) {
|
|
2089
|
+
const locale = options?.locale;
|
|
2090
|
+
if (locale) {
|
|
2091
|
+
const map = __runjsClassLocaleMeta.get(this) || new Map<string, RunJSDocMeta>();
|
|
2092
|
+
const prev = map.get(locale) || {};
|
|
2093
|
+
map.set(locale, __runjsDeepMerge(prev, meta));
|
|
2094
|
+
__runjsClassLocaleMeta.set(this, map);
|
|
2095
|
+
} else {
|
|
2096
|
+
const prev = __runjsClassDefaultMeta.get(this) || {};
|
|
2097
|
+
__runjsClassDefaultMeta.set(this, __runjsDeepMerge(prev, meta));
|
|
2098
|
+
}
|
|
2099
|
+
__runjsDocCache.delete(this);
|
|
2100
|
+
}
|
|
2101
|
+
static getDoc(locale?: string): RunJSDocMeta {
|
|
2102
|
+
const self = this as any as Function;
|
|
2103
|
+
let cacheForClass = __runjsDocCache.get(self);
|
|
2104
|
+
const cacheKey = String(locale || 'default');
|
|
2105
|
+
if (cacheForClass && cacheForClass.has(cacheKey)) return cacheForClass.get(cacheKey) as RunJSDocMeta;
|
|
2106
|
+
const chain: Function[] = [];
|
|
2107
|
+
let cur: any = self;
|
|
2108
|
+
while (cur && cur.prototype) {
|
|
2109
|
+
chain.unshift(cur);
|
|
2110
|
+
cur = Object.getPrototypeOf(cur);
|
|
2111
|
+
}
|
|
2112
|
+
let merged: RunJSDocMeta = {};
|
|
2113
|
+
for (const cls of chain) {
|
|
2114
|
+
merged = __runjsDeepMerge(merged, __runjsClassDefaultMeta.get(cls) || {});
|
|
2115
|
+
}
|
|
2116
|
+
if (locale) {
|
|
2117
|
+
for (const cls of chain) {
|
|
2118
|
+
const lmap = __runjsClassLocaleMeta.get(cls);
|
|
2119
|
+
if (lmap && lmap.has(locale)) {
|
|
2120
|
+
merged = __runjsDeepMerge(merged, lmap.get(locale));
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
if (!cacheForClass) {
|
|
2125
|
+
cacheForClass = new Map<string, RunJSDocMeta>();
|
|
2126
|
+
__runjsDocCache.set(self, cacheForClass);
|
|
2127
|
+
}
|
|
2128
|
+
cacheForClass.set(cacheKey, merged);
|
|
2129
|
+
return merged;
|
|
2130
|
+
}
|
|
2131
|
+
}
|