feat: dsl check plugin

This commit is contained in:
StyleZhang 2024-11-13 15:48:06 +08:00
parent edbfe27eb1
commit 577a948f42
7 changed files with 94 additions and 4 deletions

View File

@ -21,8 +21,9 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { getRedirection } from '@/utils/app-redirection' import { getRedirection } from '@/utils/app-redirection'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useMutationCheckDependenciesBeforeImportDSL } from '@/service/use-plugins'
interface CreateFromDSLModalProps { type CreateFromDSLModalProps = {
show: boolean show: boolean
onSuccess?: () => void onSuccess?: () => void
onClose: () => void onClose: () => void
@ -43,6 +44,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
const [fileContent, setFileContent] = useState<string>() const [fileContent, setFileContent] = useState<string>()
const [currentTab, setCurrentTab] = useState(activeTab) const [currentTab, setCurrentTab] = useState(activeTab)
const [dslUrlValue, setDslUrlValue] = useState(dslUrl) const [dslUrlValue, setDslUrlValue] = useState(dslUrl)
const { mutateAsync } = useMutationCheckDependenciesBeforeImportDSL()
const readFile = (file: File) => { const readFile = (file: File) => {
const reader = new FileReader() const reader = new FileReader()
@ -78,11 +80,21 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
let app let app
if (currentTab === CreateFromDSLModalTab.FROM_FILE) { if (currentTab === CreateFromDSLModalTab.FROM_FILE) {
const leakedData = await mutateAsync({ dslString: fileContent })
if (leakedData?.leaked.length) {
isCreatingRef.current = false
return
}
app = await importApp({ app = await importApp({
data: fileContent || '', data: fileContent || '',
}) })
} }
if (currentTab === CreateFromDSLModalTab.FROM_URL) { if (currentTab === CreateFromDSLModalTab.FROM_URL) {
const leakedData = await mutateAsync({ url: dslUrlValue })
if (leakedData?.leaked.length) {
isCreatingRef.current = false
return
}
app = await importAppFromUrl({ app = await importAppFromUrl({
url: dslUrlValue || '', url: dslUrlValue || '',
}) })

View File

@ -305,3 +305,15 @@ export type UninstallPluginResponse = {
export type PluginsFromMarketplaceResponse = { export type PluginsFromMarketplaceResponse = {
plugins: Plugin[] 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
}
}

View File

@ -72,6 +72,7 @@ import SyncingDataModal from './syncing-data-modal'
import UpdateDSLModal from './update-dsl-modal' import UpdateDSLModal from './update-dsl-modal'
import DSLExportConfirmModal from './dsl-export-confirm-modal' import DSLExportConfirmModal from './dsl-export-confirm-modal'
import LimitTips from './limit-tips' import LimitTips from './limit-tips'
import PluginDependency from './plugin-dependency'
import { import {
useStore, useStore,
useWorkflowStore, useWorkflowStore,
@ -105,7 +106,7 @@ const edgeTypes = {
[CUSTOM_NODE]: CustomEdge, [CUSTOM_NODE]: CustomEdge,
} }
interface WorkflowProps { type WorkflowProps = {
nodes: Node[] nodes: Node[]
edges: Edge[] edges: Edge[]
viewport?: Viewport viewport?: Viewport
@ -326,6 +327,7 @@ const Workflow: FC<WorkflowProps> = memo(({
/> />
) )
} }
<PluginDependency />
<LimitTips /> <LimitTips />
<ReactFlow <ReactFlow
nodeTypes={nodeTypes} nodeTypes={nodeTypes}

View File

@ -0,0 +1,14 @@
import { useStore } from './store'
const PluginDependency = () => {
const dependencies = useStore(s => s.dependencies)
if (!dependencies.length)
return null
return (
<div>a</div>
)
}
export default PluginDependency

View File

@ -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<Shape>(set => ({
dependencies: [],
setDependencies: dependencies => set({ dependencies }),
}))

View File

@ -29,8 +29,9 @@ import { updateWorkflowDraftFromDSL } from '@/service/workflow'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
import { useMutationCheckDependenciesBeforeImportDSL } from '@/service/use-plugins'
interface UpdateDSLModalProps { type UpdateDSLModalProps = {
onCancel: () => void onCancel: () => void
onBackup: () => void onBackup: () => void
onImport?: () => void onImport?: () => void
@ -48,6 +49,7 @@ const UpdateDSLModal = ({
const [fileContent, setFileContent] = useState<string>() const [fileContent, setFileContent] = useState<string>()
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()
const { mutateAsync, mutate } = useMutationCheckDependenciesBeforeImportDSL()
const readFile = (file: File) => { const readFile = (file: File) => {
const reader = new FileReader() const reader = new FileReader()
@ -75,6 +77,11 @@ const UpdateDSLModal = ({
return return
try { try {
if (appDetail && fileContent) { if (appDetail && fileContent) {
const leakedData = await mutateAsync({ dslString: fileContent })
if (leakedData?.leaked.length) {
isCreatingRef.current = false
return
}
setLoading(true) setLoading(true)
const { const {
graph, graph,
@ -128,7 +135,7 @@ const UpdateDSLModal = ({
notify({ type: 'error', message: t('workflow.common.importFailure') }) notify({ type: 'error', message: t('workflow.common.importFailure') })
} }
isCreatingRef.current = false isCreatingRef.current = false
}, [currentFile, fileContent, onCancel, notify, t, eventEmitter, appDetail, onImport]) }, [currentFile, fileContent, onCancel, notify, t, eventEmitter, appDetail, onImport, mutateAsync])
return ( return (
<Modal <Modal

View File

@ -1,6 +1,7 @@
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import type { import type {
DebugInfo as DebugInfoTypes, DebugInfo as DebugInfoTypes,
Dependency,
InstallPackageResponse, InstallPackageResponse,
InstalledPluginListResponse, InstalledPluginListResponse,
Permissions, Permissions,
@ -16,6 +17,7 @@ import {
useQuery, useQuery,
useQueryClient, useQueryClient,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import { useStore as usePluginDependencyStore } from '@/app/components/workflow/plugin-dependency/store'
const NAME_SPACE = 'plugins' const NAME_SPACE = 'plugins'
@ -161,3 +163,33 @@ export const useMutationClearTaskPlugin = () => {
}, },
}) })
} }
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
}