diff --git a/web/app/components/plugins/install-plugin/base/check-task-status.ts b/web/app/components/plugins/install-plugin/base/check-task-status.ts index 96d6171aaf..320f50d70a 100644 --- a/web/app/components/plugins/install-plugin/base/check-task-status.ts +++ b/web/app/components/plugins/install-plugin/base/check-task-status.ts @@ -1,6 +1,7 @@ import { checkTaskStatus as fetchCheckTaskStatus } from '@/service/plugins' import type { PluginStatus } from '../../types' import { TaskStatus } from '../../types' +import { sleep } from '@/utils' const INTERVAL = 10 * 1000 // 10 seconds @@ -17,31 +18,37 @@ function checkTaskStatus() { taskId, pluginUniqueIdentifier, }: Params) => { - if (isStop) return + if (isStop) { + return { + status: TaskStatus.success, + } + } const res = await fetchCheckTaskStatus(taskId) const { plugins } = res.task const plugin = plugins.find((p: PluginStatus) => p.plugin_unique_identifier === pluginUniqueIdentifier) if (!plugin) { nextStatus = TaskStatus.failed - Promise.reject(new Error('Plugin package not found')) - return + return { + status: TaskStatus.failed, + error: 'Plugin package not found', + } } nextStatus = plugin.status if (nextStatus === TaskStatus.running) { - setTimeout(async () => { - await doCheckStatus({ - taskId, - pluginUniqueIdentifier, - }) - }, INTERVAL) - return + await sleep(INTERVAL) + return await doCheckStatus({ + taskId, + pluginUniqueIdentifier, + }) } if (nextStatus === TaskStatus.failed) { - Promise.reject(plugin.message) - return + return { + status: TaskStatus.failed, + error: plugin.message, + } } return ({ - status: nextStatus, + status: TaskStatus.success, }) } diff --git a/web/app/components/plugins/install-plugin/base/version.tsx b/web/app/components/plugins/install-plugin/base/version.tsx index 891294f095..67bbc8ed2e 100644 --- a/web/app/components/plugins/install-plugin/base/version.tsx +++ b/web/app/components/plugins/install-plugin/base/version.tsx @@ -2,14 +2,9 @@ import type { FC } from 'react' import React from 'react' import Badge, { BadgeState } from '@/app/components/base/badge/index' +import type { VersionProps } from '../../types' -type Props = { - hasInstalled: boolean - installedVersion?: string - toInstallVersion: string -} - -const Version: FC = ({ +const Version: FC = ({ hasInstalled, installedVersion, toInstallVersion, diff --git a/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx index 5b35128049..e72648fcec 100644 --- a/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx +++ b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx @@ -1,6 +1,7 @@ import { useCheckInstalled as useDoCheckInstalled } from '@/service/use-plugins' import { useMemo } from 'react' +import type { VersionInfo } from '../../types' type Props = { pluginIds: string[], enabled: boolean @@ -12,10 +13,7 @@ const useCheckInstalled = (props: Props) => { if (!data) return undefined - const res: Record = {} + const res: Record = {} data?.plugins.forEach((plugin) => { res[plugin.plugin_id] = { installedVersion: plugin.declaration.version, diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx index 8440b488b2..96abaa2e1c 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx @@ -6,11 +6,13 @@ import { pluginManifestToCardPluginProps } from '../../utils' import { useUploadGitHub } from '@/service/use-plugins' import Loading from '../../base/loading' import LoadedItem from './loaded-item' +import type { VersionProps } from '@/app/components/plugins/types' type Props = { checked: boolean onCheckedChange: (plugin: Plugin) => void dependency: GitHubItemAndMarketPlaceDependency + versionInfo: VersionProps onFetchedPayload: (payload: Plugin) => void onFetchError: () => void } @@ -19,6 +21,7 @@ const Item: FC = ({ checked, onCheckedChange, dependency, + versionInfo, onFetchedPayload, onFetchError, }) => { @@ -50,6 +53,7 @@ const Item: FC = ({ return ( diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx index 9b503245ce..5eb4c94abe 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx @@ -4,15 +4,17 @@ import React from 'react' import type { Plugin } from '../../../types' import Card from '../../../card' import Checkbox from '@/app/components/base/checkbox' -import Badge, { BadgeState } from '@/app/components/base/badge/index' import useGetIcon from '../../base/use-get-icon' import { MARKETPLACE_API_PREFIX } from '@/config' +import Version from '../../base/version' +import type { VersionProps } from '../../../types' type Props = { checked: boolean onCheckedChange: (plugin: Plugin) => void payload: Plugin isFromMarketPlace?: boolean + versionInfo: VersionProps } const LoadedItem: FC = ({ @@ -20,8 +22,13 @@ const LoadedItem: FC = ({ onCheckedChange, payload, isFromMarketPlace, + versionInfo: particleVersionInfo, }) => { const { getIconUrl } = useGetIcon() + const versionInfo = { + ...particleVersionInfo, + toInstallVersion: payload.version, + } return (
= ({ ...payload, icon: isFromMarketPlace ? `${MARKETPLACE_API_PREFIX}/plugins/${payload.org}/${payload.name}/icon` : getIconUrl(payload.icon), }} - titleLeft={payload.version ? {payload.version} : null} + titleLeft={payload.version ? : null} />
) diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx index f7de4d09bc..3389bdb0ad 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx @@ -4,25 +4,31 @@ import React from 'react' import type { Plugin } from '../../../types' import Loading from '../../base/loading' import LoadedItem from './loaded-item' +import type { VersionProps } from '@/app/components/plugins/types' type Props = { checked: boolean onCheckedChange: (plugin: Plugin) => void payload?: Plugin + version: string + versionInfo: VersionProps } const MarketPlaceItem: FC = ({ checked, onCheckedChange, payload, + version, + versionInfo, }) => { if (!payload) return return ( ) } diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx index 97ee6b0de6..101c8facaf 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx @@ -6,12 +6,14 @@ import type { PackageDependency } from '../../../types' import { pluginManifestToCardPluginProps } from '../../utils' import LoadedItem from './loaded-item' import LoadingError from '../../base/loading-error' +import type { VersionProps } from '@/app/components/plugins/types' type Props = { checked: boolean onCheckedChange: (plugin: Plugin) => void payload: PackageDependency isFromMarketPlace?: boolean + versionInfo: VersionProps } const PackageItem: FC = ({ @@ -19,6 +21,7 @@ const PackageItem: FC = ({ checked, onCheckedChange, isFromMarketPlace, + versionInfo, }) => { if (!payload.value?.manifest) return @@ -30,6 +33,7 @@ const PackageItem: FC = ({ checked={checked} onCheckedChange={onCheckedChange} isFromMarketPlace={isFromMarketPlace} + versionInfo={versionInfo} /> ) } diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx index e8bf71297d..48b1ecd325 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx @@ -1,10 +1,11 @@ 'use client' import type { FC } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react' -import type { Dependency, GitHubItemAndMarketPlaceDependency, PackageDependency, Plugin } from '../../../types' +import type { Dependency, GitHubItemAndMarketPlaceDependency, PackageDependency, Plugin, VersionInfo } from '../../../types' import MarketplaceItem from '../item/marketplace-item' import GithubItem from '../item/github-item' import { useFetchPluginsInMarketPlaceByIds, useFetchPluginsInMarketPlaceByInfo } from '@/service/use-plugins' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' import produce from 'immer' import PackageItem from '../item/package-item' import LoadingError from '../../base/loading-error' @@ -13,7 +14,7 @@ type Props = { allPlugins: Dependency[] selectedPlugins: Plugin[] onSelect: (plugin: Plugin, selectedIndex: number) => void - onLoadedAllPlugin: () => void + onLoadedAllPlugin: (installedInfo: Record) => void isFromMarketPlace?: boolean } @@ -28,6 +29,7 @@ const InstallByDSLList: FC = ({ const { isLoading: isFetchingMarketplaceDataById, data: infoGetById, error: infoByIdError } = useFetchPluginsInMarketPlaceByIds(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value.plugin_unique_identifier!)) // has meta(org,name,version), to get id const { isLoading: isFetchingDataByMeta, data: infoByMeta, error: infoByMetaError } = useFetchPluginsInMarketPlaceByInfo(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value!)) + const [plugins, doSetPlugins] = useState<(Plugin | undefined)[]>((() => { const hasLocalPackage = allPlugins.some(d => d.type === 'package') if (!hasLocalPackage) @@ -45,6 +47,7 @@ const InstallByDSLList: FC = ({ }) return _plugins })()) + const pluginsRef = React.useRef<(Plugin | undefined)[]>(plugins) const setPlugins = useCallback((p: (Plugin | undefined)[]) => { @@ -132,11 +135,30 @@ const InstallByDSLList: FC = ({ }, [infoByMetaError, infoByIdError]) const isLoadedAllData = (plugins.filter(p => !!p).length + errorIndexes.length) === allPlugins.length + + const { installedInfo } = useCheckInstalled({ + pluginIds: plugins?.filter(p => !!p).map((d) => { + return `${d?.org || d?.author}/${d?.name}` + }) || [], + enabled: isLoadedAllData, + }) + + const getVersionInfo = useCallback((pluginId: string) => { + const pluginDetail = installedInfo?.[pluginId] + const hasInstalled = !!pluginDetail + return { + hasInstalled, + installedVersion: pluginDetail?.installedVersion, + toInstallVersion: '', + } + }, [installedInfo]) + useEffect(() => { - if (isLoadedAllData) - onLoadedAllPlugin() + if (isLoadedAllData && installedInfo) + onLoadedAllPlugin(installedInfo!) + // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoadedAllData]) + }, [isLoadedAllData, installedInfo]) const handleSelect = useCallback((index: number) => { return () => { @@ -151,6 +173,7 @@ const InstallByDSLList: FC = ({ ) } + const plugin = plugins[index] if (d.type === 'github') { return ( = ({ dependency={d as GitHubItemAndMarketPlaceDependency} onFetchedPayload={handleGitHubPluginFetched(index)} onFetchError={handleGitHubPluginFetchError(index)} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} />) } @@ -169,6 +193,8 @@ const InstallByDSLList: FC = ({ checked={!!selectedPlugins.find(p => p.plugin_id === plugins[index]?.plugin_id)} onCheckedChange={handleSelect(index)} payload={plugins[index] as Plugin} + version={(d as GitHubItemAndMarketPlaceDependency).value.version!} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} /> ) } @@ -181,6 +207,7 @@ const InstallByDSLList: FC = ({ onCheckedChange={handleSelect(index)} payload={d as PackageDependency} isFromMarketPlace={isFromMarketPlace} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} /> ) }) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx index f2bd2e86bf..7f33c5cef3 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx @@ -1,12 +1,12 @@ 'use client' import type { FC } from 'react' -import React, { useCallback } from 'react' -import type { Dependency, InstallStatusResponse, Plugin } from '../../../types' +import React, { useCallback, useState } from 'react' +import type { Dependency, InstallStatusResponse, Plugin, VersionInfo } from '../../../types' import Button from '@/app/components/base/button' import { RiLoader2Line } from '@remixicon/react' import { useTranslation } from 'react-i18next' import InstallMulti from './install-multi' -import { useInstallFromMarketplaceAndGitHub } from '@/service/use-plugins' +import { useInstallOrUpdate } from '@/service/use-plugins' import { useInvalidateInstalledPluginList } from '@/service/use-plugins' const i18nPrefix = 'plugin.installModal' @@ -43,12 +43,15 @@ const Install: FC = ({ } const [canInstall, setCanInstall] = React.useState(false) - const handleLoadedAllPlugin = useCallback(() => { + const [installedInfo, setInstalledInfo] = useState | undefined>(undefined) + + const handleLoadedAllPlugin = useCallback((installedInfo: Record | undefined) => { + setInstalledInfo(installedInfo) setCanInstall(true) }, []) // Install from marketplace and github - const { mutate: installFromMarketplaceAndGitHub, isPending: isInstalling } = useInstallFromMarketplaceAndGitHub({ + const { mutate: installOrUpdate, isPending: isInstalling } = useInstallOrUpdate({ onSuccess: (res: InstallStatusResponse[]) => { onInstalled(selectedPlugins, res.map((r, i) => { return ({ @@ -62,9 +65,10 @@ const Install: FC = ({ }, }) const handleInstall = () => { - installFromMarketplaceAndGitHub({ + installOrUpdate({ payload: allPlugins.filter((_d, index) => selectedIndexes.includes(index)), plugin: selectedPlugins, + installedInfo: installedInfo!, }) } return ( diff --git a/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx index d4f15c0de4..195ff43d00 100644 --- a/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx +++ b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx @@ -2,7 +2,7 @@ import React from 'react' import Button from '@/app/components/base/button' -import type { PluginDeclaration, PluginType, UpdateFromGitHubPayload } from '../../../types' +import { type PluginDeclaration, type PluginType, TaskStatus, type UpdateFromGitHubPayload } from '../../../types' import Card from '../../../card' import Badge, { BadgeState } from '@/app/components/base/badge/index' import { pluginManifestToCardPluginProps } from '../../utils' @@ -53,8 +53,9 @@ const Loaded: React.FC = ({ try { const { owner, repo } = parseGitHubUrl(repoUrl) + let taskId if (updatePayload) { - const { all_installed: isInstalled, task_id: taskId } = await updateFromGitHub( + const { all_installed: isInstalled, task_id } = await updateFromGitHub( `${owner}/${repo}`, selectedVersion, selectedPackage, @@ -62,40 +63,42 @@ const Loaded: React.FC = ({ uniqueIdentifier, ) + taskId = task_id + if (isInstalled) { onInstalled() return } handleRefetch() - await check({ - taskId, - pluginUniqueIdentifier: uniqueIdentifier, - }) - - onInstalled() } else { - const { all_installed: isInstalled, task_id: taskId } = await installPackageFromGitHub({ + const { all_installed: isInstalled, task_id } = await installPackageFromGitHub({ repoUrl: `${owner}/${repo}`, selectedVersion, selectedPackage, uniqueIdentifier, }) + taskId = task_id + if (isInstalled) { onInstalled() return } handleRefetch() - await check({ - taskId, - pluginUniqueIdentifier: uniqueIdentifier, - }) - - onInstalled() } + + const { status, error } = await check({ + taskId, + pluginUniqueIdentifier: uniqueIdentifier, + }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } + onInstalled() } catch (e) { if (typeof e === 'string') { diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx index d37275f19a..13d766cbad 100644 --- a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx @@ -1,7 +1,7 @@ 'use client' import type { FC } from 'react' import React, { useEffect } from 'react' -import type { PluginDeclaration } from '../../../types' +import { type PluginDeclaration, TaskStatus } from '../../../types' import Card from '../../../card' import { pluginManifestToCardPluginProps } from '../../utils' import Button from '@/app/components/base/button' @@ -43,9 +43,9 @@ const Installed: FC = ({ const hasInstalled = !!installedVersion useEffect(() => { - if (hasInstalled && toInstallVersion === installedVersion) + if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) onInstalled() - }, [hasInstalled, toInstallVersion, installedVersion]) + }, [hasInstalled]) const [isInstalling, setIsInstalling] = React.useState(false) const { mutateAsync: installPackageFromLocal } = useInstallPackageFromLocal() @@ -95,10 +95,14 @@ const Installed: FC = ({ return } handleRefetch() - await check({ + const { status, error } = await check({ taskId, pluginUniqueIdentifier: uniqueIdentifier, }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } onInstalled() } catch (e) { diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx index 0b3728e2a1..a3bb50076b 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -2,7 +2,7 @@ import type { FC } from 'react' import React, { useEffect } from 'react' // import { RiInformation2Line } from '@remixicon/react' -import type { Plugin, PluginManifestInMarket } from '../../../types' +import { type Plugin, type PluginManifestInMarket, TaskStatus } from '../../../types' import Card from '../../../card' import { pluginManifestInMarketToPluginProps } from '../../utils' import Button from '@/app/components/base/button' @@ -52,9 +52,9 @@ const Installed: FC = ({ } = checkTaskStatus() useEffect(() => { - if (hasInstalled && toInstallVersion === installedVersion) + if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) onInstalled() - }, [hasInstalled, toInstallVersion, installedVersion]) + }, [hasInstalled]) const handleCancel = () => { stop() @@ -93,10 +93,14 @@ const Installed: FC = ({ onInstalled() return } - await check({ + const { status, error } = await check({ taskId, pluginUniqueIdentifier: uniqueIdentifier, }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } onInstalled() } catch (e) { diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 1ab127ec55..7a44c7dd56 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -109,6 +109,7 @@ export type PluginDetail = { export type Plugin = { type: 'plugin' | 'bundle' org: string + author?: string name: string plugin_id: string version: string @@ -359,3 +360,14 @@ export type Version = { export type VersionListResponse = { versions: Version[] } + +export type VersionInfo = { + installedVersion: string, + uniqueIdentifier: string +} + +export type VersionProps = { + hasInstalled: boolean + installedVersion?: string + toInstallVersion: string +} diff --git a/web/app/components/plugins/update-plugin/from-market-place.tsx b/web/app/components/plugins/update-plugin/from-market-place.tsx index e4abd32aff..6177ddce1a 100644 --- a/web/app/components/plugins/update-plugin/from-market-place.tsx +++ b/web/app/components/plugins/update-plugin/from-market-place.tsx @@ -7,12 +7,13 @@ import Card from '@/app/components/plugins/card' import Modal from '@/app/components/base/modal' import Button from '@/app/components/base/button' import Badge, { BadgeState } from '@/app/components/base/badge/index' -import type { UpdateFromMarketPlacePayload } from '../types' +import { TaskStatus, type UpdateFromMarketPlacePayload } from '../types' import { pluginManifestToCardPluginProps } from '@/app/components/plugins/install-plugin/utils' import useGetIcon from '../install-plugin/base/use-get-icon' import { updateFromMarketPlace } from '@/service/plugins' import checkTaskStatus from '@/app/components/plugins/install-plugin/base/check-task-status' import { usePluginTaskList } from '@/service/use-plugins' +import Toast from '../../base/toast' const i18nPrefix = 'plugin.upgrade' @@ -83,10 +84,14 @@ const UpdatePluginModal: FC = ({ return } handleRefetch() - await check({ + const { status, error } = await check({ taskId, pluginUniqueIdentifier: targetPackageInfo.id, }) + if (status === TaskStatus.failed) { + Toast.notify({ type: 'error', message: error! }) + return + } onSave() } // eslint-disable-next-line unused-imports/no-unused-vars diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts index 50003a2f1a..8ddca80ae1 100644 --- a/web/service/use-plugins.ts +++ b/web/service/use-plugins.ts @@ -12,6 +12,7 @@ import type { PluginTask, PluginsFromMarketplaceByInfoResponse, PluginsFromMarketplaceResponse, + VersionInfo, VersionListResponse, uploadGitHubResponse, } from '@/app/components/plugins/types' @@ -145,22 +146,30 @@ export const useUploadGitHub = (payload: { }) } -export const useInstallFromMarketplaceAndGitHub = ({ +export const useInstallOrUpdate = ({ onSuccess, }: { onSuccess?: (res: { success: boolean }[]) => void }) => { + const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace() + return useMutation({ mutationFn: (data: { payload: Dependency[], plugin: Plugin[], + installedInfo: Record }) => { - const { payload, plugin } = data + const { payload, plugin, installedInfo } = data + return Promise.all(payload.map(async (item, i) => { try { + const orgAndName = `${plugin[i]?.org || plugin[i]?.author}/${plugin[i]?.name}` + const installedPayload = installedInfo[orgAndName] + const isInstalled = !!installedPayload + let uniqueIdentifier = '' + if (item.type === 'github') { const data = item as GitHubItemAndMarketPlaceDependency - let pluginId = '' // From local bundle don't have data.value.github_plugin_unique_identifier if (!data.value.github_plugin_unique_identifier) { const { unique_identifier } = await post('/workspaces/current/plugin/upload/github', { @@ -170,32 +179,61 @@ export const useInstallFromMarketplaceAndGitHub = ({ package: data.value.packages! || data.value.package!, }, }) - pluginId = unique_identifier + uniqueIdentifier = data.value.github_plugin_unique_identifier! || unique_identifier + // has the same version, but not installed + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + } + if (!isInstalled) { + await post('/workspaces/current/plugin/install/github', { + body: { + repo: data.value.repo!, + version: data.value.release! || data.value.version!, + package: data.value.packages! || data.value.package!, + plugin_unique_identifier: uniqueIdentifier, + }, + }) } - await post('/workspaces/current/plugin/install/github', { - body: { - repo: data.value.repo!, - version: data.value.release! || data.value.version!, - package: data.value.packages! || data.value.package!, - plugin_unique_identifier: data.value.github_plugin_unique_identifier! || pluginId, - }, - }) } if (item.type === 'marketplace') { const data = item as GitHubItemAndMarketPlaceDependency - - await post('/workspaces/current/plugin/install/marketplace', { - body: { - plugin_unique_identifiers: [data.value.plugin_unique_identifier! || plugin[i]?.plugin_id], - }, - }) + uniqueIdentifier = data.value.plugin_unique_identifier! || plugin[i]?.plugin_id + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + if (!isInstalled) { + await post('/workspaces/current/plugin/install/marketplace', { + body: { + plugin_unique_identifiers: [uniqueIdentifier], + }, + }) + } } if (item.type === 'package') { const data = item as PackageDependency - await post('/workspaces/current/plugin/install/pkg', { - body: { - plugin_unique_identifiers: [data.value.unique_identifier], - }, + uniqueIdentifier = data.value.unique_identifier + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + if (!isInstalled) { + await post('/workspaces/current/plugin/install/pkg', { + body: { + plugin_unique_identifiers: [uniqueIdentifier], + }, + }) + } + } + if (isInstalled) { + await updatePackageFromMarketPlace({ + original_plugin_unique_identifier: installedPayload?.uniqueIdentifier, + new_plugin_unique_identifier: uniqueIdentifier, }) } return ({ success: true })