mirror of
https://github.com/langgenius/dify.git
synced 2026-04-25 17:47:30 +08:00
Merge branch 'feat/plugins' of github.com:langgenius/dify into feat/plugins
This commit is contained in:
commit
8533ded335
@ -29,3 +29,6 @@ NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS=60000
|
|||||||
|
|
||||||
# CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
# CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||||
NEXT_PUBLIC_CSP_WHITELIST=
|
NEXT_PUBLIC_CSP_WHITELIST=
|
||||||
|
|
||||||
|
# Github Access Token, used for invoking Github API
|
||||||
|
NEXT_PUBLIC_GITHUB_ACCESS_TOKEN=
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import { toolNeko } from '@/app/components/plugins/card/card-mock'
|
||||||
import { PluginSource } from '@/app/components/plugins/types'
|
import { PluginSource } from '@/app/components/plugins/types'
|
||||||
import { useModalContext } from '@/context/modal-context'
|
import { useModalContext } from '@/context/modal-context'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@ -11,11 +12,12 @@ const UpdatePlugin = () => {
|
|||||||
type: PluginSource.marketplace,
|
type: PluginSource.marketplace,
|
||||||
marketPlace: {
|
marketPlace: {
|
||||||
originalPackageInfo: {
|
originalPackageInfo: {
|
||||||
id: 'original_xxx',
|
id: 'langgenius/neko:0.0.1@9e57d693739287c0efdc96847d7ed959ca93f70aa704471f2eb7ed3313821824',
|
||||||
|
payload: toolNeko as any,
|
||||||
},
|
},
|
||||||
targetPackageInfo: {
|
targetPackageInfo: {
|
||||||
id: 'target_xxx',
|
id: 'target_xxx',
|
||||||
payload: {} as any,
|
version: '1.2.3',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -32,9 +34,14 @@ const UpdatePlugin = () => {
|
|||||||
payload: {
|
payload: {
|
||||||
type: PluginSource.github,
|
type: PluginSource.github,
|
||||||
github: {
|
github: {
|
||||||
repo: 'repo_xxx',
|
originalPackageInfo: {
|
||||||
originalPluginId: 'original_xxx',
|
id: '111',
|
||||||
version: 'version_xxx',
|
repo: 'aaa/bbb',
|
||||||
|
version: 'xxx',
|
||||||
|
url: 'aaa/bbb',
|
||||||
|
currVersion: '1.2.3',
|
||||||
|
currPackage: 'pack1',
|
||||||
|
} as any,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onCancelCallback: () => {
|
onCancelCallback: () => {
|
||||||
|
|||||||
@ -1,6 +1,64 @@
|
|||||||
import type { PluginDeclaration } from '../types'
|
import type { PluginDeclaration } from '../types'
|
||||||
import { PluginType } from '../types'
|
import { PluginType } from '../types'
|
||||||
|
|
||||||
|
export const toolNeko: PluginDeclaration = {
|
||||||
|
version: '0.0.1',
|
||||||
|
author: 'langgenius',
|
||||||
|
name: 'neko',
|
||||||
|
description: {
|
||||||
|
en_US: 'Neko is a cute cat.',
|
||||||
|
zh_Hans: '这是一只可爱的小猫。',
|
||||||
|
pt_BR: 'Neko is a cute cat.',
|
||||||
|
ja_JP: 'Neko is a cute cat.',
|
||||||
|
},
|
||||||
|
icon: '241e5209ecc8b5ce6b7a29a8e50388e9c75b89c3047c6ecd8e552f26de758883.svg',
|
||||||
|
label: {
|
||||||
|
en_US: 'Neko',
|
||||||
|
zh_Hans: 'Neko',
|
||||||
|
pt_BR: 'Neko',
|
||||||
|
ja_JP: 'Neko',
|
||||||
|
},
|
||||||
|
category: 'extension' as any,
|
||||||
|
created_at: '2024-07-12T08:03:44.658609Z',
|
||||||
|
resource: {
|
||||||
|
memory: 1048576,
|
||||||
|
permission: {
|
||||||
|
tool: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
enabled: true,
|
||||||
|
llm: true,
|
||||||
|
text_embedding: false,
|
||||||
|
rerank: false,
|
||||||
|
tts: false,
|
||||||
|
speech2text: false,
|
||||||
|
moderation: false,
|
||||||
|
},
|
||||||
|
node: null,
|
||||||
|
endpoint: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
storage: {
|
||||||
|
enabled: true,
|
||||||
|
size: 1048576,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
tools: null,
|
||||||
|
models: null,
|
||||||
|
endpoints: [
|
||||||
|
'provider/neko.yaml',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
tags: [],
|
||||||
|
verified: false,
|
||||||
|
tool: null,
|
||||||
|
model: null,
|
||||||
|
endpoint: null,
|
||||||
|
}
|
||||||
|
|
||||||
export const toolNotion = {
|
export const toolNotion = {
|
||||||
type: PluginType.tool,
|
type: PluginType.tool,
|
||||||
org: 'Notion',
|
org: 'Notion',
|
||||||
|
|||||||
@ -1,15 +1,25 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
import { uploadGitHub } from '@/service/plugins'
|
import { uploadGitHub } from '@/service/plugins'
|
||||||
|
import { Octokit } from '@octokit/core'
|
||||||
|
import { GITHUB_ACCESS_TOKEN } from '@/config'
|
||||||
|
|
||||||
export const useGitHubReleases = () => {
|
export const useGitHubReleases = () => {
|
||||||
const fetchReleases = async (owner: string, repo: string, setReleases: (releases: any) => void) => {
|
const fetchReleases = async (owner: string, repo: string) => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases`)
|
const octokit = new Octokit({
|
||||||
if (!res.ok) throw new Error('Failed to fetch releases')
|
auth: GITHUB_ACCESS_TOKEN,
|
||||||
const data = await res.json()
|
})
|
||||||
|
const res = await octokit.request('GET /repos/{owner}/{repo}/releases', {
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
headers: {
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if (res.status !== 200) throw new Error('Failed to fetch releases')
|
||||||
|
|
||||||
const formattedReleases = data.map((release: any) => ({
|
const formattedReleases = res.data.map((release: any) => ({
|
||||||
tag_name: release.tag_name,
|
tag_name: release.tag_name,
|
||||||
assets: release.assets.map((asset: any) => ({
|
assets: release.assets.map((asset: any) => ({
|
||||||
browser_download_url: asset.browser_download_url,
|
browser_download_url: asset.browser_download_url,
|
||||||
@ -17,13 +27,14 @@ export const useGitHubReleases = () => {
|
|||||||
})),
|
})),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
setReleases(formattedReleases)
|
return formattedReleases
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
Toast.notify({
|
Toast.notify({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: 'Failed to fetch repository releases',
|
message: 'Failed to fetch repository releases',
|
||||||
})
|
})
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { installPackageFromGitHub } from '@/service/plugins'
|
|||||||
type InstallFromGitHubProps = {
|
type InstallFromGitHubProps = {
|
||||||
updatePayload?: UpdateFromGitHubPayload
|
updatePayload?: UpdateFromGitHubPayload
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
|
onSuccess: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, onClose }) => {
|
const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, onClose }) => {
|
||||||
@ -118,13 +119,12 @@ const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, on
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
await fetchReleases(owner, repo, (fetchedReleases) => {
|
const fetchedReleases = await fetchReleases(owner, repo)
|
||||||
setState(prevState => ({
|
setState(prevState => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
releases: fetchedReleases,
|
releases: fetchedReleases,
|
||||||
step: InstallStepFromGitHub.selectPackage,
|
step: InstallStepFromGitHub.selectPackage,
|
||||||
}))
|
}))
|
||||||
})
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case InstallStepFromGitHub.selectPackage: {
|
case InstallStepFromGitHub.selectPackage: {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ const InstallFromLocalPackage: React.FC<InstallFromLocalPackageProps> = ({
|
|||||||
return t(`${i18nPrefix}.installFailed`)
|
return t(`${i18nPrefix}.installFailed`)
|
||||||
|
|
||||||
return t(`${i18nPrefix}.installPlugin`)
|
return t(`${i18nPrefix}.installPlugin`)
|
||||||
}, [step])
|
}, [step, t])
|
||||||
|
|
||||||
const { getIconUrl } = useGetIcon()
|
const { getIconUrl } = useGetIcon()
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ const InstallFromLocalPackage: React.FC<InstallFromLocalPackageProps> = ({
|
|||||||
icon,
|
icon,
|
||||||
})
|
})
|
||||||
setStep(InstallStep.readyToInstall)
|
setStep(InstallStep.readyToInstall)
|
||||||
}, [])
|
}, [getIconUrl])
|
||||||
|
|
||||||
const handleUploadFail = useCallback((errorMsg: string) => {
|
const handleUploadFail = useCallback((errorMsg: string) => {
|
||||||
setErrorMsg(errorMsg)
|
setErrorMsg(errorMsg)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import type { GitHubUrlInfo } from '@/app/components/plugins/types'
|
|||||||
|
|
||||||
export const pluginManifestToCardPluginProps = (pluginManifest: PluginDeclaration): Plugin => {
|
export const pluginManifestToCardPluginProps = (pluginManifest: PluginDeclaration): Plugin => {
|
||||||
return {
|
return {
|
||||||
|
plugin_id: pluginManifest.plugin_unique_identifier,
|
||||||
type: pluginManifest.category,
|
type: pluginManifest.category,
|
||||||
category: pluginManifest.category,
|
category: pluginManifest.category,
|
||||||
name: pluginManifest.name,
|
name: pluginManifest.name,
|
||||||
@ -25,6 +26,7 @@ export const pluginManifestToCardPluginProps = (pluginManifest: PluginDeclaratio
|
|||||||
|
|
||||||
export const pluginManifestInMarketToPluginProps = (pluginManifest: PluginManifestInMarket): Plugin => {
|
export const pluginManifestInMarketToPluginProps = (pluginManifest: PluginManifestInMarket): Plugin => {
|
||||||
return {
|
return {
|
||||||
|
plugin_id: pluginManifest.plugin_unique_identifier,
|
||||||
type: pluginManifest.category,
|
type: pluginManifest.category,
|
||||||
category: pluginManifest.category,
|
category: pluginManifest.category,
|
||||||
name: pluginManifest.name,
|
name: pluginManifest.name,
|
||||||
|
|||||||
@ -10,13 +10,17 @@ import ActionButton from '../../base/action-button'
|
|||||||
import Tooltip from '../../base/tooltip'
|
import Tooltip from '../../base/tooltip'
|
||||||
import Confirm from '../../base/confirm'
|
import Confirm from '../../base/confirm'
|
||||||
import { uninstallPlugin } from '@/service/plugins'
|
import { uninstallPlugin } from '@/service/plugins'
|
||||||
import { usePluginPageContext } from '../plugin-page/context'
|
import { useGitHubReleases } from '../install-plugin/hooks'
|
||||||
|
import { compareVersion, getLatestVersion } from '@/utils/semver'
|
||||||
|
import Toast from '@/app/components/base/toast'
|
||||||
|
|
||||||
const i18nPrefix = 'plugin.action'
|
const i18nPrefix = 'plugin.action'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
pluginId: string
|
author: string
|
||||||
|
installationId: string
|
||||||
pluginName: string
|
pluginName: string
|
||||||
|
version: string
|
||||||
usedInApps: number
|
usedInApps: number
|
||||||
isShowFetchNewVersion: boolean
|
isShowFetchNewVersion: boolean
|
||||||
isShowInfo: boolean
|
isShowInfo: boolean
|
||||||
@ -25,8 +29,10 @@ type Props = {
|
|||||||
meta?: MetaData
|
meta?: MetaData
|
||||||
}
|
}
|
||||||
const Action: FC<Props> = ({
|
const Action: FC<Props> = ({
|
||||||
pluginId,
|
author,
|
||||||
|
installationId,
|
||||||
pluginName,
|
pluginName,
|
||||||
|
version,
|
||||||
isShowFetchNewVersion,
|
isShowFetchNewVersion,
|
||||||
isShowInfo,
|
isShowInfo,
|
||||||
isShowDelete,
|
isShowDelete,
|
||||||
@ -38,13 +44,35 @@ const Action: FC<Props> = ({
|
|||||||
setTrue: showPluginInfo,
|
setTrue: showPluginInfo,
|
||||||
setFalse: hidePluginInfo,
|
setFalse: hidePluginInfo,
|
||||||
}] = useBoolean(false)
|
}] = useBoolean(false)
|
||||||
const mutateInstalledPluginList = usePluginPageContext(v => v.mutateInstalledPluginList)
|
|
||||||
const [deleting, {
|
const [deleting, {
|
||||||
setTrue: showDeleting,
|
setTrue: showDeleting,
|
||||||
setFalse: hideDeleting,
|
setFalse: hideDeleting,
|
||||||
}] = useBoolean(false)
|
}] = useBoolean(false)
|
||||||
|
const { fetchReleases } = useGitHubReleases()
|
||||||
|
|
||||||
const handleFetchNewVersion = () => { }
|
const handleFetchNewVersion = async () => {
|
||||||
|
try {
|
||||||
|
const fetchedReleases = await fetchReleases(author, pluginName)
|
||||||
|
const versions = fetchedReleases.map(release => release.tag_name)
|
||||||
|
const latestVersion = getLatestVersion(versions)
|
||||||
|
if (compareVersion(latestVersion, version) === 1) {
|
||||||
|
// todo: open plugin updating modal
|
||||||
|
console.log('New version available:', latestVersion)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toast.notify({
|
||||||
|
type: 'info',
|
||||||
|
message: 'No new version available',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Toast.notify({
|
||||||
|
type: 'error',
|
||||||
|
message: 'Failed to compare versions',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [isShowDeleteConfirm, {
|
const [isShowDeleteConfirm, {
|
||||||
setTrue: showDeleteConfirm,
|
setTrue: showDeleteConfirm,
|
||||||
@ -53,14 +81,13 @@ const Action: FC<Props> = ({
|
|||||||
|
|
||||||
const handleDelete = useCallback(async () => {
|
const handleDelete = useCallback(async () => {
|
||||||
showDeleting()
|
showDeleting()
|
||||||
const res = await uninstallPlugin(pluginId)
|
const res = await uninstallPlugin(installationId)
|
||||||
hideDeleting()
|
hideDeleting()
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
hideDeleteConfirm()
|
hideDeleteConfirm()
|
||||||
mutateInstalledPluginList()
|
|
||||||
onDelete()
|
onDelete()
|
||||||
}
|
}
|
||||||
}, [pluginId, onDelete])
|
}, [installationId])
|
||||||
return (
|
return (
|
||||||
<div className='flex space-x-1'>
|
<div className='flex space-x-1'>
|
||||||
{/* Only plugin installed from GitHub need to check if it's the new version */}
|
{/* Only plugin installed from GitHub need to check if it's the new version */}
|
||||||
|
|||||||
@ -37,6 +37,7 @@ const PluginItem: FC<Props> = ({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const currentPluginDetail = usePluginPageContext(v => v.currentPluginDetail)
|
const currentPluginDetail = usePluginPageContext(v => v.currentPluginDetail)
|
||||||
const setCurrentPluginDetail = usePluginPageContext(v => v.setCurrentPluginDetail)
|
const setCurrentPluginDetail = usePluginPageContext(v => v.setCurrentPluginDetail)
|
||||||
|
const mutateInstalledPluginList = usePluginPageContext(v => v.mutateInstalledPluginList)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
source,
|
source,
|
||||||
@ -44,16 +45,10 @@ const PluginItem: FC<Props> = ({
|
|||||||
installation_id,
|
installation_id,
|
||||||
endpoints_active,
|
endpoints_active,
|
||||||
meta,
|
meta,
|
||||||
version,
|
|
||||||
latest_version,
|
|
||||||
plugin_id,
|
plugin_id,
|
||||||
|
version,
|
||||||
} = plugin
|
} = plugin
|
||||||
const { category, author, name, label, description, icon, verified } = plugin.declaration
|
const { category, author, name, label, description, icon, verified } = plugin.declaration
|
||||||
// Only plugin installed from GitHub need to check if it's the new version
|
|
||||||
// todo check version manually
|
|
||||||
const hasNewVersion = useMemo(() => {
|
|
||||||
return source === PluginSource.github && latest_version !== version
|
|
||||||
}, [source, latest_version, version])
|
|
||||||
|
|
||||||
const orgName = useMemo(() => {
|
const orgName = useMemo(() => {
|
||||||
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
|
return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : ''
|
||||||
@ -79,6 +74,7 @@ const PluginItem: FC<Props> = ({
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className='flex items-center justify-center w-10 h-10 overflow-hidden border-components-panel-border-subtle border-[1px] rounded-xl'>
|
<div className='flex items-center justify-center w-10 h-10 overflow-hidden border-components-panel-border-subtle border-[1px] rounded-xl'>
|
||||||
<img
|
<img
|
||||||
|
className='w-full h-full'
|
||||||
src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`}
|
src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`}
|
||||||
alt={`plugin-${installation_id}-logo`}
|
alt={`plugin-${installation_id}-logo`}
|
||||||
/>
|
/>
|
||||||
@ -87,20 +83,24 @@ const PluginItem: FC<Props> = ({
|
|||||||
<div className="flex items-center h-5">
|
<div className="flex items-center h-5">
|
||||||
<Title title={label[tLocale]} />
|
<Title title={label[tLocale]} />
|
||||||
{verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />}
|
{verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />}
|
||||||
<Badge className='ml-1' text={plugin.version} hasRedCornerMark={hasNewVersion} />
|
<Badge className='ml-1' text={plugin.version} />
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<Description text={description[tLocale]} descriptionLineRows={1}></Description>
|
<Description text={description[tLocale]} descriptionLineRows={1}></Description>
|
||||||
<div onClick={e => e.stopPropagation()}>
|
<div onClick={e => e.stopPropagation()}>
|
||||||
<Action
|
<Action
|
||||||
pluginId={installation_id}
|
installationId={installation_id}
|
||||||
pluginName={label[tLocale]}
|
author={author}
|
||||||
|
pluginName={name}
|
||||||
|
version={version}
|
||||||
usedInApps={5}
|
usedInApps={5}
|
||||||
isShowFetchNewVersion={hasNewVersion}
|
isShowFetchNewVersion={source === PluginSource.github}
|
||||||
isShowInfo={source === PluginSource.github}
|
isShowInfo={source === PluginSource.github}
|
||||||
isShowDelete
|
isShowDelete
|
||||||
meta={meta}
|
meta={meta}
|
||||||
onDelete={() => {}}
|
onDelete={() => {
|
||||||
|
mutateInstalledPluginList()
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -54,6 +54,7 @@ export type EndpointListItem = {
|
|||||||
|
|
||||||
// Plugin manifest
|
// Plugin manifest
|
||||||
export type PluginDeclaration = {
|
export type PluginDeclaration = {
|
||||||
|
plugin_unique_identifier: string
|
||||||
version: string
|
version: string
|
||||||
author: string
|
author: string
|
||||||
icon: string
|
icon: string
|
||||||
@ -71,6 +72,7 @@ export type PluginDeclaration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PluginManifestInMarket = {
|
export type PluginManifestInMarket = {
|
||||||
|
plugin_unique_identifier: string
|
||||||
name: string
|
name: string
|
||||||
org: string
|
org: string
|
||||||
icon: string
|
icon: string
|
||||||
@ -137,17 +139,18 @@ export type Permissions = {
|
|||||||
export type UpdateFromMarketPlacePayload = {
|
export type UpdateFromMarketPlacePayload = {
|
||||||
originalPackageInfo: {
|
originalPackageInfo: {
|
||||||
id: string
|
id: string
|
||||||
|
payload: PluginDeclaration
|
||||||
},
|
},
|
||||||
targetPackageInfo: {
|
targetPackageInfo: {
|
||||||
id: string
|
id: string
|
||||||
payload: PluginDeclaration
|
version: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateFromGitHubPayload = {
|
export type UpdateFromGitHubPayload = {
|
||||||
originalPackageInfo: {
|
originalPackageInfo: {
|
||||||
|
id: string
|
||||||
repo: string
|
repo: string
|
||||||
originalPluginId: string
|
|
||||||
version: string
|
version: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { UpdateFromGitHubPayload } from '../types'
|
import type { UpdateFromGitHubPayload } from '../types'
|
||||||
|
import InstallFromGitHub from '../install-plugin/install-from-github'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
payload: UpdateFromGitHubPayload
|
payload: UpdateFromGitHubPayload
|
||||||
@ -11,11 +12,15 @@ type Props = {
|
|||||||
|
|
||||||
const FromGitHub: FC<Props> = ({
|
const FromGitHub: FC<Props> = ({
|
||||||
payload,
|
payload,
|
||||||
|
onSave,
|
||||||
|
onCancel,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<InstallFromGitHub
|
||||||
{JSON.stringify(payload)}
|
updatePayload={payload}
|
||||||
</div>
|
onClose={onCancel}
|
||||||
|
onSuccess={onSave}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default React.memo(FromGitHub)
|
export default React.memo(FromGitHub)
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { RiInformation2Line } from '@remixicon/react'
|
import { RiInformation2Line } from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Card from '@/app/components/plugins/card'
|
import Card from '@/app/components/plugins/card'
|
||||||
import Modal from '@/app/components/base/modal'
|
import Modal from '@/app/components/base/modal'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import Badge, { BadgeState } from '@/app/components/base/badge/index'
|
import Badge, { BadgeState } from '@/app/components/base/badge/index'
|
||||||
import { toolNotion } from '@/app/components/plugins/card/card-mock'
|
|
||||||
import type { UpdateFromMarketPlacePayload } from '../types'
|
import type { UpdateFromMarketPlacePayload } from '../types'
|
||||||
|
import { pluginManifestToCardPluginProps } from '@/app/components/plugins/install-plugin/utils'
|
||||||
|
import useGetIcon from '../install-plugin/base/use-get-icon'
|
||||||
|
|
||||||
const i18nPrefix = 'plugin.upgrade'
|
const i18nPrefix = 'plugin.upgrade'
|
||||||
|
|
||||||
@ -25,10 +26,23 @@ enum UploadStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UpdatePluginModal: FC<Props> = ({
|
const UpdatePluginModal: FC<Props> = ({
|
||||||
|
payload,
|
||||||
onSave,
|
onSave,
|
||||||
onCancel,
|
onCancel,
|
||||||
}) => {
|
}) => {
|
||||||
|
const {
|
||||||
|
originalPackageInfo,
|
||||||
|
targetPackageInfo,
|
||||||
|
} = payload
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { getIconUrl } = useGetIcon()
|
||||||
|
const [icon, setIcon] = useState<string>(originalPackageInfo.payload.icon)
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const icon = await getIconUrl(originalPackageInfo.payload.icon)
|
||||||
|
setIcon(icon)
|
||||||
|
})()
|
||||||
|
}, [originalPackageInfo, getIconUrl])
|
||||||
const [uploadStep, setUploadStep] = useState<UploadStep>(UploadStep.notStarted)
|
const [uploadStep, setUploadStep] = useState<UploadStep>(UploadStep.notStarted)
|
||||||
const configBtnText = useMemo(() => {
|
const configBtnText = useMemo(() => {
|
||||||
return ({
|
return ({
|
||||||
@ -65,12 +79,15 @@ const UpdatePluginModal: FC<Props> = ({
|
|||||||
<div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'>
|
<div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'>
|
||||||
<Card
|
<Card
|
||||||
installed={uploadStep === UploadStep.installed}
|
installed={uploadStep === UploadStep.installed}
|
||||||
payload={toolNotion as any}
|
payload={pluginManifestToCardPluginProps({
|
||||||
|
...originalPackageInfo.payload,
|
||||||
|
icon: icon!,
|
||||||
|
})}
|
||||||
className='w-full'
|
className='w-full'
|
||||||
titleLeft={
|
titleLeft={
|
||||||
<>
|
<>
|
||||||
<Badge className='mx-1' size="s" state={BadgeState.Warning}>
|
<Badge className='mx-1' size="s" state={BadgeState.Warning}>
|
||||||
{'1.2.0 -> 1.3.2'}
|
{`${originalPackageInfo.payload.version} -> ${targetPackageInfo.version}`}
|
||||||
</Badge>
|
</Badge>
|
||||||
<div className='flex px-0.5 justify-center items-center gap-0.5'>
|
<div className='flex px-0.5 justify-center items-center gap-0.5'>
|
||||||
<div className='text-text-warning system-xs-medium'>{t(`${i18nPrefix}.usedInApps`, { num: 3 })}</div>
|
<div className='text-text-warning system-xs-medium'>{t(`${i18nPrefix}.usedInApps`, { num: 3 })}</div>
|
||||||
|
|||||||
@ -45,6 +45,7 @@ const LocaleLayout = ({
|
|||||||
data-public-maintenance-notice={process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE}
|
data-public-maintenance-notice={process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE}
|
||||||
data-public-site-about={process.env.NEXT_PUBLIC_SITE_ABOUT}
|
data-public-site-about={process.env.NEXT_PUBLIC_SITE_ABOUT}
|
||||||
data-public-text-generation-timeout-ms={process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS}
|
data-public-text-generation-timeout-ms={process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS}
|
||||||
|
data-public-github-access-token={process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN}
|
||||||
>
|
>
|
||||||
<BrowserInitor>
|
<BrowserInitor>
|
||||||
<SentryInitor>
|
<SentryInitor>
|
||||||
|
|||||||
@ -271,3 +271,5 @@ else if (globalThis.document?.body?.getAttribute('data-public-text-generation-ti
|
|||||||
export const TEXT_GENERATION_TIMEOUT_MS = textGenerationTimeoutMs
|
export const TEXT_GENERATION_TIMEOUT_MS = textGenerationTimeoutMs
|
||||||
|
|
||||||
export const DISABLE_UPLOAD_IMAGE_AS_ICON = process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON === 'true'
|
export const DISABLE_UPLOAD_IMAGE_AS_ICON = process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON === 'true'
|
||||||
|
|
||||||
|
export const GITHUB_ACCESS_TOKEN = process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN || globalThis.document?.body?.getAttribute('data-public-github-access-token') || ''
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
"@mdx-js/react": "^2.3.0",
|
"@mdx-js/react": "^2.3.0",
|
||||||
"@monaco-editor/react": "^4.6.0",
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"@next/mdx": "^14.0.4",
|
"@next/mdx": "^14.0.4",
|
||||||
|
"@octokit/core": "^6.1.2",
|
||||||
"@remixicon/react": "^4.3.0",
|
"@remixicon/react": "^4.3.0",
|
||||||
"@sentry/react": "^7.54.0",
|
"@sentry/react": "^7.54.0",
|
||||||
"@sentry/utils": "^7.54.0",
|
"@sentry/utils": "^7.54.0",
|
||||||
@ -98,6 +99,7 @@
|
|||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"scheduler": "^0.23.0",
|
"scheduler": "^0.23.0",
|
||||||
|
"semver": "^7.6.3",
|
||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
@ -144,6 +146,7 @@
|
|||||||
"@types/react-window": "^1.8.8",
|
"@types/react-window": "^1.8.8",
|
||||||
"@types/react-window-infinite-loader": "^1.0.9",
|
"@types/react-window-infinite-loader": "^1.0.9",
|
||||||
"@types/recordrtc": "^5.6.14",
|
"@types/recordrtc": "^5.6.14",
|
||||||
|
"@types/semver": "^7.5.8",
|
||||||
"@types/sortablejs": "^1.15.1",
|
"@types/sortablejs": "^1.15.1",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
@ -153,9 +156,9 @@
|
|||||||
"eslint": "^9.13.0",
|
"eslint": "^9.13.0",
|
||||||
"eslint-config-next": "^15.0.0",
|
"eslint-config-next": "^15.0.0",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"husky": "^9.1.6",
|
|
||||||
"eslint-plugin-react-refresh": "^0.4.13",
|
"eslint-plugin-react-refresh": "^0.4.13",
|
||||||
"eslint-plugin-storybook": "^0.10.1",
|
"eslint-plugin-storybook": "^0.10.1",
|
||||||
|
"husky": "^9.1.6",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"lint-staged": "^15.2.10",
|
"lint-staged": "^15.2.10",
|
||||||
|
|||||||
95
web/pnpm-lock.yaml
generated
95
web/pnpm-lock.yaml
generated
@ -52,6 +52,9 @@ importers:
|
|||||||
'@next/mdx':
|
'@next/mdx':
|
||||||
specifier: ^14.0.4
|
specifier: ^14.0.4
|
||||||
version: 14.2.15(@mdx-js/loader@2.3.0(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)))(@mdx-js/react@2.3.0(react@18.2.0))
|
version: 14.2.15(@mdx-js/loader@2.3.0(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)))(@mdx-js/react@2.3.0(react@18.2.0))
|
||||||
|
'@octokit/core':
|
||||||
|
specifier: ^6.1.2
|
||||||
|
version: 6.1.2
|
||||||
'@remixicon/react':
|
'@remixicon/react':
|
||||||
specifier: ^4.3.0
|
specifier: ^4.3.0
|
||||||
version: 4.3.0(react@18.2.0)
|
version: 4.3.0(react@18.2.0)
|
||||||
@ -235,6 +238,9 @@ importers:
|
|||||||
scheduler:
|
scheduler:
|
||||||
specifier: ^0.23.0
|
specifier: ^0.23.0
|
||||||
version: 0.23.2
|
version: 0.23.2
|
||||||
|
semver:
|
||||||
|
specifier: ^7.6.3
|
||||||
|
version: 7.6.3
|
||||||
server-only:
|
server-only:
|
||||||
specifier: ^0.0.1
|
specifier: ^0.0.1
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
@ -368,6 +374,9 @@ importers:
|
|||||||
'@types/recordrtc':
|
'@types/recordrtc':
|
||||||
specifier: ^5.6.14
|
specifier: ^5.6.14
|
||||||
version: 5.6.14
|
version: 5.6.14
|
||||||
|
'@types/semver':
|
||||||
|
specifier: ^7.5.8
|
||||||
|
version: 7.5.8
|
||||||
'@types/sortablejs':
|
'@types/sortablejs':
|
||||||
specifier: ^1.15.1
|
specifier: ^1.15.1
|
||||||
version: 1.15.8
|
version: 1.15.8
|
||||||
@ -1871,6 +1880,36 @@ packages:
|
|||||||
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
|
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
|
||||||
engines: {node: '>=12.4.0'}
|
engines: {node: '>=12.4.0'}
|
||||||
|
|
||||||
|
'@octokit/auth-token@5.1.1':
|
||||||
|
resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/core@6.1.2':
|
||||||
|
resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/endpoint@10.1.1':
|
||||||
|
resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/graphql@8.1.1':
|
||||||
|
resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/openapi-types@22.2.0':
|
||||||
|
resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==}
|
||||||
|
|
||||||
|
'@octokit/request-error@6.1.5':
|
||||||
|
resolution: {integrity: sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/request@9.1.3':
|
||||||
|
resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==}
|
||||||
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
'@octokit/types@13.6.1':
|
||||||
|
resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==}
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.4.1':
|
'@parcel/watcher-android-arm64@2.4.1':
|
||||||
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
|
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
@ -3158,6 +3197,9 @@ packages:
|
|||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
before-after-hook@3.0.2:
|
||||||
|
resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==}
|
||||||
|
|
||||||
better-opn@3.0.2:
|
better-opn@3.0.2:
|
||||||
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
|
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@ -7806,6 +7848,9 @@ packages:
|
|||||||
unist-util-visit@5.0.0:
|
unist-util-visit@5.0.0:
|
||||||
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
||||||
|
|
||||||
|
universal-user-agent@7.0.2:
|
||||||
|
resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==}
|
||||||
|
|
||||||
universalify@0.2.0:
|
universalify@0.2.0:
|
||||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||||
engines: {node: '>= 4.0.0'}
|
engines: {node: '>= 4.0.0'}
|
||||||
@ -9925,6 +9970,46 @@ snapshots:
|
|||||||
|
|
||||||
'@nolyfill/is-core-module@1.0.39': {}
|
'@nolyfill/is-core-module@1.0.39': {}
|
||||||
|
|
||||||
|
'@octokit/auth-token@5.1.1': {}
|
||||||
|
|
||||||
|
'@octokit/core@6.1.2':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/auth-token': 5.1.1
|
||||||
|
'@octokit/graphql': 8.1.1
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/request-error': 6.1.5
|
||||||
|
'@octokit/types': 13.6.1
|
||||||
|
before-after-hook: 3.0.2
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/endpoint@10.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 13.6.1
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/graphql@8.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/request': 9.1.3
|
||||||
|
'@octokit/types': 13.6.1
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/openapi-types@22.2.0': {}
|
||||||
|
|
||||||
|
'@octokit/request-error@6.1.5':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/types': 13.6.1
|
||||||
|
|
||||||
|
'@octokit/request@9.1.3':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/endpoint': 10.1.1
|
||||||
|
'@octokit/request-error': 6.1.5
|
||||||
|
'@octokit/types': 13.6.1
|
||||||
|
universal-user-agent: 7.0.2
|
||||||
|
|
||||||
|
'@octokit/types@13.6.1':
|
||||||
|
dependencies:
|
||||||
|
'@octokit/openapi-types': 22.2.0
|
||||||
|
|
||||||
'@parcel/watcher-android-arm64@2.4.1':
|
'@parcel/watcher-android-arm64@2.4.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@ -11618,6 +11703,8 @@ snapshots:
|
|||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
|
before-after-hook@3.0.2: {}
|
||||||
|
|
||||||
better-opn@3.0.2:
|
better-opn@3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
open: 8.4.2
|
open: 8.4.2
|
||||||
@ -12757,7 +12844,7 @@ snapshots:
|
|||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
enhanced-resolve: 5.17.1
|
enhanced-resolve: 5.17.1
|
||||||
eslint: 9.13.0(jiti@1.21.6)
|
eslint: 9.13.0(jiti@1.21.6)
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6))
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.8.1
|
get-tsconfig: 4.8.1
|
||||||
is-bun-module: 1.2.1
|
is-bun-module: 1.2.1
|
||||||
@ -12775,7 +12862,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.13.0(jiti@1.21.6)
|
eslint: 9.13.0(jiti@1.21.6)
|
||||||
|
|
||||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6)):
|
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@ -12831,7 +12918,7 @@ snapshots:
|
|||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 9.13.0(jiti@1.21.6)
|
eslint: 9.13.0(jiti@1.21.6)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))
|
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6))
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.15.1
|
is-core-module: 2.15.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@ -17577,6 +17664,8 @@ snapshots:
|
|||||||
unist-util-is: 6.0.0
|
unist-util-is: 6.0.0
|
||||||
unist-util-visit-parents: 6.0.1
|
unist-util-visit-parents: 6.0.1
|
||||||
|
|
||||||
|
universal-user-agent@7.0.2: {}
|
||||||
|
|
||||||
universalify@0.2.0: {}
|
universalify@0.2.0: {}
|
||||||
|
|
||||||
universalify@2.0.1: {}
|
universalify@2.0.1: {}
|
||||||
|
|||||||
9
web/utils/semver.ts
Normal file
9
web/utils/semver.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import semver from 'semver'
|
||||||
|
|
||||||
|
export const getLatestVersion = (versionList: string[]) => {
|
||||||
|
return semver.rsort(versionList)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const compareVersion = (v1: string, v2: string) => {
|
||||||
|
return semver.compare(v1, v2)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user