From 577a948f42e6a9e7d8ab764d03a2a5abe0c640b3 Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Wed, 13 Nov 2024 15:48:06 +0800 Subject: [PATCH] feat: dsl check plugin --- .../app/create-from-dsl-modal/index.tsx | 14 +++++++- web/app/components/plugins/types.ts | 12 +++++++ web/app/components/workflow/index.tsx | 4 ++- .../workflow/plugin-dependency/index.tsx | 14 ++++++++ .../workflow/plugin-dependency/store.ts | 11 +++++++ .../components/workflow/update-dsl-modal.tsx | 11 +++++-- web/service/use-plugins.ts | 32 +++++++++++++++++++ 7 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 web/app/components/workflow/plugin-dependency/index.tsx create mode 100644 web/app/components/workflow/plugin-dependency/store.ts diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index a97ca97bbe..45ef8dbde6 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -21,8 +21,9 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { getRedirection } from '@/utils/app-redirection' import cn from '@/utils/classnames' +import { useMutationCheckDependenciesBeforeImportDSL } from '@/service/use-plugins' -interface CreateFromDSLModalProps { +type CreateFromDSLModalProps = { show: boolean onSuccess?: () => void onClose: () => void @@ -43,6 +44,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS const [fileContent, setFileContent] = useState() const [currentTab, setCurrentTab] = useState(activeTab) const [dslUrlValue, setDslUrlValue] = useState(dslUrl) + const { mutateAsync } = useMutationCheckDependenciesBeforeImportDSL() const readFile = (file: File) => { const reader = new FileReader() @@ -78,11 +80,21 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS let app if (currentTab === CreateFromDSLModalTab.FROM_FILE) { + const leakedData = await mutateAsync({ dslString: fileContent }) + if (leakedData?.leaked.length) { + isCreatingRef.current = false + return + } app = await importApp({ data: fileContent || '', }) } if (currentTab === CreateFromDSLModalTab.FROM_URL) { + const leakedData = await mutateAsync({ url: dslUrlValue }) + if (leakedData?.leaked.length) { + isCreatingRef.current = false + return + } app = await importAppFromUrl({ url: dslUrlValue || '', }) diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 4d9ae8ca35..e42dff0f5c 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -305,3 +305,15 @@ export type UninstallPluginResponse = { export type PluginsFromMarketplaceResponse = { plugins: Plugin[] } + +export type Dependency = { + type: 'github' | 'marketplace' | 'package' + value: { + repo?: string + version?: string + package?: string + github_plugin_unique_identifier?: string + marketplace_plugin_unique_identifier?: string + plugin_unique_identifier?: string + } +} diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 3a5a790919..2eccb38e47 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -72,6 +72,7 @@ import SyncingDataModal from './syncing-data-modal' import UpdateDSLModal from './update-dsl-modal' import DSLExportConfirmModal from './dsl-export-confirm-modal' import LimitTips from './limit-tips' +import PluginDependency from './plugin-dependency' import { useStore, useWorkflowStore, @@ -105,7 +106,7 @@ const edgeTypes = { [CUSTOM_NODE]: CustomEdge, } -interface WorkflowProps { +type WorkflowProps = { nodes: Node[] edges: Edge[] viewport?: Viewport @@ -326,6 +327,7 @@ const Workflow: FC = memo(({ /> ) } + { + const dependencies = useStore(s => s.dependencies) + + if (!dependencies.length) + return null + + return ( +
a
+ ) +} + +export default PluginDependency diff --git a/web/app/components/workflow/plugin-dependency/store.ts b/web/app/components/workflow/plugin-dependency/store.ts new file mode 100644 index 0000000000..a8e1d8171a --- /dev/null +++ b/web/app/components/workflow/plugin-dependency/store.ts @@ -0,0 +1,11 @@ +import { create } from 'zustand' +import type { Dependency } from '@/app/components/plugins/types' + +type Shape = { + dependencies: Dependency[] + setDependencies: (dependencies: Dependency[]) => void +} +export const useStore = create(set => ({ + dependencies: [], + setDependencies: dependencies => set({ dependencies }), +})) diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx index d91b7ca04b..86a3648c4e 100644 --- a/web/app/components/workflow/update-dsl-modal.tsx +++ b/web/app/components/workflow/update-dsl-modal.tsx @@ -29,8 +29,9 @@ import { updateWorkflowDraftFromDSL } from '@/service/workflow' import { useEventEmitterContextContext } from '@/context/event-emitter' import { useStore as useAppStore } from '@/app/components/app/store' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' +import { useMutationCheckDependenciesBeforeImportDSL } from '@/service/use-plugins' -interface UpdateDSLModalProps { +type UpdateDSLModalProps = { onCancel: () => void onBackup: () => void onImport?: () => void @@ -48,6 +49,7 @@ const UpdateDSLModal = ({ const [fileContent, setFileContent] = useState() const [loading, setLoading] = useState(false) const { eventEmitter } = useEventEmitterContextContext() + const { mutateAsync, mutate } = useMutationCheckDependenciesBeforeImportDSL() const readFile = (file: File) => { const reader = new FileReader() @@ -75,6 +77,11 @@ const UpdateDSLModal = ({ return try { if (appDetail && fileContent) { + const leakedData = await mutateAsync({ dslString: fileContent }) + if (leakedData?.leaked.length) { + isCreatingRef.current = false + return + } setLoading(true) const { graph, @@ -128,7 +135,7 @@ const UpdateDSLModal = ({ notify({ type: 'error', message: t('workflow.common.importFailure') }) } isCreatingRef.current = false - }, [currentFile, fileContent, onCancel, notify, t, eventEmitter, appDetail, onImport]) + }, [currentFile, fileContent, onCancel, notify, t, eventEmitter, appDetail, onImport, mutateAsync]) return ( { }, }) } + +export const useMutationCheckDependenciesBeforeImportDSL = () => { + const mutation = useMutation({ + mutationFn: ({ dslString, url }: { dslString?: string, url?: string }) => { + if (url) { + return post<{ leaked: Dependency[] }>( + '/apps/import/url/dependencies/check', + { + body: { + url, + }, + }, + ) + } + return post<{ leaked: Dependency[] }>( + '/apps/import/dependencies/check', + { + body: { + data: dslString, + }, + }) + }, + onSuccess: (data) => { + const { setDependencies } = usePluginDependencyStore.getState() + setDependencies(data.leaked || []) + }, + }) + + return mutation +}