[Manager] Fix package version matching in conflict detection (#4530)

Co-authored-by: Jin Yi <jin12cc@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
comfy-jinyi
2025-07-25 14:10:55 +09:00
committed by GitHub
parent b169772f9f
commit 7c2a648ab8
10 changed files with 143 additions and 113 deletions

View File

@@ -252,20 +252,25 @@ const getVersionData = (version: string) => {
nodePack.supported_comfyui_frontend_version, nodePack.supported_comfyui_frontend_version,
supported_python_version: supported_python_version:
(latestVersionData && 'supported_python_version' in latestVersionData (latestVersionData && 'supported_python_version' in latestVersionData
? latestVersionData.supported_python_version as string | undefined ? (latestVersionData.supported_python_version as string | undefined)
: undefined) ?? : undefined) ??
('supported_python_version' in nodePack ('supported_python_version' in nodePack
? nodePack.supported_python_version as string | undefined ? (nodePack.supported_python_version as string | undefined)
: undefined), : undefined),
is_banned: is_banned:
(latestVersionData && 'is_banned' in latestVersionData (latestVersionData && 'is_banned' in latestVersionData
? latestVersionData.is_banned as boolean | undefined ? (latestVersionData.is_banned as boolean | undefined)
: undefined) ?? ('is_banned' in nodePack ? nodePack.is_banned as boolean | undefined : false), : undefined) ??
('is_banned' in nodePack
? (nodePack.is_banned as boolean | undefined)
: false),
has_registry_data: has_registry_data:
(latestVersionData && 'has_registry_data' in latestVersionData (latestVersionData && 'has_registry_data' in latestVersionData
? latestVersionData.has_registry_data as boolean | undefined ? (latestVersionData.has_registry_data as boolean | undefined)
: undefined) ?? : undefined) ??
('has_registry_data' in nodePack ? nodePack.has_registry_data as boolean | undefined : false) ('has_registry_data' in nodePack
? (nodePack.has_registry_data as boolean | undefined)
: false)
} }
} }
@@ -281,7 +286,7 @@ const getVersionData = (version: string) => {
nodePack.supported_comfyui_frontend_version, // Use latest known requirement nodePack.supported_comfyui_frontend_version, // Use latest known requirement
supported_python_version: supported_python_version:
'supported_python_version' in nodePack 'supported_python_version' in nodePack
? nodePack.supported_python_version as string | undefined ? (nodePack.supported_python_version as string | undefined)
: undefined, : undefined,
is_banned: false, // Nightly versions from repositories are typically not banned is_banned: false, // Nightly versions from repositories are typically not banned
has_registry_data: false // Nightly doesn't come from registry has_registry_data: false // Nightly doesn't come from registry
@@ -299,12 +304,15 @@ const getVersionData = (version: string) => {
versionData.supported_comfyui_frontend_version, versionData.supported_comfyui_frontend_version,
supported_python_version: supported_python_version:
'supported_python_version' in versionData 'supported_python_version' in versionData
? versionData.supported_python_version as string | undefined ? (versionData.supported_python_version as string | undefined)
: undefined, : undefined,
is_banned: 'is_banned' in versionData ? versionData.is_banned as boolean | undefined : false, is_banned:
'is_banned' in versionData
? (versionData.is_banned as boolean | undefined)
: false,
has_registry_data: has_registry_data:
'has_registry_data' in versionData 'has_registry_data' in versionData
? versionData.has_registry_data as boolean | undefined ? (versionData.has_registry_data as boolean | undefined)
: false : false
} }
} }
@@ -318,11 +326,16 @@ const getVersionData = (version: string) => {
nodePack.supported_comfyui_frontend_version, nodePack.supported_comfyui_frontend_version,
supported_python_version: supported_python_version:
'supported_python_version' in nodePack 'supported_python_version' in nodePack
? nodePack.supported_python_version as string | undefined ? (nodePack.supported_python_version as string | undefined)
: undefined, : undefined,
is_banned: 'is_banned' in nodePack ? nodePack.is_banned as boolean | undefined : false, is_banned:
'is_banned' in nodePack
? (nodePack.is_banned as boolean | undefined)
: false,
has_registry_data: has_registry_data:
'has_registry_data' in nodePack ? nodePack.has_registry_data as boolean | undefined : false 'has_registry_data' in nodePack
? (nodePack.has_registry_data as boolean | undefined)
: false
} }
} }

View File

@@ -42,7 +42,7 @@ const { nodePack, hasConflict } = defineProps<{
const { t } = useI18n() const { t } = useI18n()
const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore() const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore()
const conflictStore = useConflictDetectionStore() const { getConflictsForPackageByID } = useConflictDetectionStore()
const { showNodeConflictDialog } = useDialogService() const { showNodeConflictDialog } = useDialogService()
const { acknowledgeConflict, isConflictAcknowledged } = const { acknowledgeConflict, isConflictAcknowledged } =
useConflictAcknowledgment() useConflictAcknowledgment()
@@ -87,7 +87,7 @@ const handleToggle = async (enable: boolean, skipConflictCheck = false) => {
// Check for conflicts when enabling // Check for conflicts when enabling
if (enable && hasConflict && !skipConflictCheck) { if (enable && hasConflict && !skipConflictCheck) {
const conflicts = conflictStore.getConflictsForPackage(nodePack.id || '') const conflicts = getConflictsForPackageByID(nodePack.id || '')
if (conflicts) { if (conflicts) {
// Check if conflicts have been acknowledged // Check if conflicts have been acknowledged
const hasUnacknowledgedConflicts = conflicts.conflicts.some( const hasUnacknowledgedConflicts = conflicts.conflicts.some(
@@ -141,7 +141,7 @@ const onToggle = debounce(
// Show conflict modal when warning icon is clicked // Show conflict modal when warning icon is clicked
const showConflictModal = () => { const showConflictModal = () => {
const conflicts = conflictStore.getConflictsForPackage(nodePack.id || '') const conflicts = getConflictsForPackageByID(nodePack.id || '')
if (conflicts) { if (conflicts) {
showNodeConflictDialog({ showNodeConflictDialog({
conflictedPackages: [conflicts], conflictedPackages: [conflicts],

View File

@@ -62,12 +62,15 @@ const nodeNames = computed(() => {
const activeTab = ref('description') const activeTab = ref('description')
// Watch for compatibility issues and automatically switch to warning tab // Watch for compatibility issues and automatically switch to warning tab
watchEffect(() => { watchEffect(
if (hasCompatibilityIssues) { () => {
activeTab.value = 'warning' if (hasCompatibilityIssues) {
} else if (activeTab.value === 'warning') { activeTab.value = 'warning'
// If currently on warning tab but no issues, switch to description } else if (activeTab.value === 'warning') {
activeTab.value = 'description' // If currently on warning tab but no issues, switch to description
} activeTab.value = 'description'
}, { flush: 'post' }) }
},
{ flush: 'post' }
)
</script> </script>

View File

@@ -44,20 +44,16 @@ const formattedDownloads = computed(() =>
nodePack.downloads ? n(nodePack.downloads) : '' nodePack.downloads ? n(nodePack.downloads) : ''
) )
const conflictStore = useConflictDetectionStore() const { getConflictsForPackageByID } = useConflictDetectionStore()
const { checkVersionCompatibility } = useConflictDetection() const { checkVersionCompatibility } = useConflictDetection()
// TODO: Package version mismatch issue - Package IDs include version suffixes (@1_0_3)
// but UI searches without version. This causes conflict detection failures.
// Once getConflictsForPackage is improved to handle version matching properly,
// all the complex fallback logic below can be removed.
const hasConflict = computed(() => { const hasConflict = computed(() => {
if (!nodePack.id) return false if (!nodePack.id) return false
// For installed packages, check conflicts from store // For installed packages, check conflicts from store
if (isInstalled.value) { if (isInstalled.value) {
// Try exact match first // Try exact match first
let conflicts = conflictStore.getConflictsForPackage(nodePack.id) let conflicts = getConflictsForPackageByID(nodePack.id)
if (conflicts) return true if (conflicts) return true
return false return false

View File

@@ -46,13 +46,13 @@ const { nodePack } = defineProps<{
}>() }>()
const { isPackInstalled } = useComfyManagerStore() const { isPackInstalled } = useComfyManagerStore()
const conflictStore = useConflictDetectionStore() const { getConflictsForPackageByID } = useConflictDetectionStore()
const isInstalled = computed(() => isPackInstalled(nodePack?.id)) const isInstalled = computed(() => isPackInstalled(nodePack?.id))
const packageConflicts = computed(() => { const packageConflicts = computed(() => {
if (!nodePack.id || !isInstalled.value) return null if (!nodePack.id || !isInstalled.value) return null
// For installed packages, check conflicts from store // For installed packages, check conflicts from store
return conflictStore.getConflictsForPackage(nodePack.id) return getConflictsForPackageByID(nodePack.id)
}) })
</script> </script>

View File

@@ -20,7 +20,10 @@ export const useInstalledPacks = (options: UseNodePacksOptions = {}) => {
packs.filter((pack) => comfyManagerStore.isPackInstalled(pack.id)) packs.filter((pack) => comfyManagerStore.isPackInstalled(pack.id))
const startFetchInstalled = async () => { const startFetchInstalled = async () => {
await comfyManagerStore.refreshInstalledList() // Only refresh if store doesn't have data yet
if (comfyManagerStore.installedPacksIds.size === 0) {
await comfyManagerStore.refreshInstalledList()
}
await startFetch() await startFetch()
} }

View File

@@ -1,10 +1,12 @@
import { uniqBy } from 'lodash' import { uniqBy } from 'lodash'
import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue' import { computed, getCurrentInstance, onUnmounted, readonly, ref } from 'vue'
import { useInstalledPacks } from '@/composables/nodePack/useInstalledPacks'
import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment' import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment'
import config from '@/config' import config from '@/config'
import { useComfyManagerService } from '@/services/comfyManagerService' import { useComfyManagerService } from '@/services/comfyManagerService'
import { useComfyRegistryService } from '@/services/comfyRegistryService' import { useComfyRegistryService } from '@/services/comfyRegistryService'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { useConflictDetectionStore } from '@/stores/conflictDetectionStore' import { useConflictDetectionStore } from '@/stores/conflictDetectionStore'
import { useSystemStatsStore } from '@/stores/systemStatsStore' import { useSystemStatsStore } from '@/stores/systemStatsStore'
import type { SystemStats } from '@/types' import type { SystemStats } from '@/types'
@@ -20,7 +22,6 @@ import type {
SupportedOS, SupportedOS,
SystemEnvironment SystemEnvironment
} from '@/types/conflictDetectionTypes' } from '@/types/conflictDetectionTypes'
import type { components as ManagerComponents } from '@/types/generatedManagerTypes'
import { import {
cleanVersion, cleanVersion,
satisfiesVersion, satisfiesVersion,
@@ -32,6 +33,16 @@ import {
* Error-resilient and asynchronous to avoid affecting other components. * Error-resilient and asynchronous to avoid affecting other components.
*/ */
export function useConflictDetection() { export function useConflictDetection() {
// Store references
const managerStore = useComfyManagerStore()
// Use installed packs composable instead of direct API calls
const {
startFetchInstalled,
installedPacks,
isReady: installedPacksReady
} = useInstalledPacks()
// State management // State management
const isDetecting = ref(false) const isDetecting = ref(false)
const lastDetectionTime = ref<string | null>(null) const lastDetectionTime = ref<string | null>(null)
@@ -178,15 +189,17 @@ export function useConflictDetection() {
*/ */
async function fetchPackageRequirements(): Promise<NodePackRequirements[]> { async function fetchPackageRequirements(): Promise<NodePackRequirements[]> {
try { try {
// Step 1: Get locally installed packages // Step 1: Use installed packs composable instead of direct API calls
const comfyManagerService = useComfyManagerService() // This follows Christian's architecture suggestion to use computed properties
const installedNodes: await startFetchInstalled() // Ensure data is loaded
| ManagerComponents['schemas']['InstalledPacksResponse']
| null = await comfyManagerService.listInstalledPacks()
if (!installedNodes) { if (
!installedPacksReady.value ||
!installedPacks.value ||
installedPacks.value.length === 0
) {
console.warn( console.warn(
'[ConflictDetection] Unable to fetch installed package information' '[ConflictDetection] No installed packages available from useInstalledPacks'
) )
return [] return []
} }
@@ -200,34 +213,34 @@ export function useConflictDetection() {
// Step 4: Fetch version-specific data in chunks to avoid overwhelming the Registry API // Step 4: Fetch version-specific data in chunks to avoid overwhelming the Registry API
// - Each chunk processes up to 30 packages concurrently // - Each chunk processes up to 30 packages concurrently
// - Results are stored in versionDataMap for later use // - Results are stored in versionDataMap for later use
const entries = Object.entries(installedNodes) // - Use installedPacks from useInstalledPacks composable
const chunkSize = 30 // 청크 크기 const chunkSize = 30
const versionDataMap = new Map< const versionDataMap = new Map<
string, string,
components['schemas']['NodeVersion'] components['schemas']['NodeVersion']
>() >()
for (let i = 0; i < entries.length; i += chunkSize) { for (let i = 0; i < installedPacks.value.length; i += chunkSize) {
const chunk = entries.slice(i, i + chunkSize) const chunk = installedPacks.value.slice(i, i + chunkSize)
const fetchTasks = chunk.map(async ([packageName, nodeInfo]) => { const fetchTasks = chunk.map(async (pack) => {
const typedNodeInfo: ManagerComponents['schemas']['ManagerPackInstalled'] = // Use pack.id which should be the normalized ID from Registry
nodeInfo const packageId = pack.id || ''
const version = typedNodeInfo.ver || 'latest' const version = pack.latest_version?.version || 'latest'
try { try {
const versionData = await registryService.getPackByVersion( const versionData = await registryService.getPackByVersion(
packageName, packageId,
version, version,
abortController.value?.signal abortController.value?.signal
) )
if (versionData) { if (versionData) {
versionDataMap.set(packageName, versionData) versionDataMap.set(packageId, versionData)
} }
} catch (error) { } catch (error) {
console.warn( console.warn(
`[ConflictDetection] Failed to fetch version data for ${packageName}@${version}:`, `[ConflictDetection] Failed to fetch version data for ${packageId}@${version}:`,
error error
) )
} }
@@ -237,21 +250,24 @@ export function useConflictDetection() {
} }
// Step 5: Combine local installation data with Registry version data // Step 5: Combine local installation data with Registry version data
// Use installedPacks from useInstalledPacks composable
const requirements: NodePackRequirements[] = [] const requirements: NodePackRequirements[] = []
for (const [packageName, nodeInfo] of Object.entries(installedNodes)) { for (const pack of installedPacks.value) {
const typedNodeInfo: ManagerComponents['schemas']['ManagerPackInstalled'] = const packageId = pack.id || ''
nodeInfo const versionData = versionDataMap.get(packageId)
const versionData = versionDataMap.get(packageName)
// Check if package is enabled using store method
const isEnabled = managerStore.isPackEnabled(packageId)
if (versionData) { if (versionData) {
// Combine local installation data with version-specific Registry data // Combine local installation data with version-specific Registry data
const requirement: NodePackRequirements = { const requirement: NodePackRequirements = {
// Basic package info // Basic package info
package_id: packageName, package_id: packageId,
package_name: packageName, // We don't need to fetch node info separately package_name: pack.name || packageId,
installed_version: typedNodeInfo.ver || 'unknown', installed_version: pack.latest_version?.version || 'unknown',
is_enabled: typedNodeInfo.enabled, is_enabled: isEnabled,
// Version-specific compatibility data // Version-specific compatibility data
supported_comfyui_version: versionData.supported_comfyui_version, supported_comfyui_version: versionData.supported_comfyui_version,
@@ -266,12 +282,11 @@ export function useConflictDetection() {
registry_status: undefined, // Node status - not critical for conflict detection registry_status: undefined, // Node status - not critical for conflict detection
version_status: versionData.status, version_status: versionData.status,
is_banned: is_banned:
versionData.status === 'NodeVersionStatusBanned' || versionData.status === 'NodeVersionStatusBanned' || !isEnabled,
!typedNodeInfo.enabled,
ban_reason: ban_reason:
versionData.status === 'NodeVersionStatusBanned' versionData.status === 'NodeVersionStatusBanned'
? 'Version is banned in Registry' ? 'Version is banned in Registry'
: !typedNodeInfo.enabled : !isEnabled
? 'Package is disabled locally' ? 'Package is disabled locally'
: undefined, : undefined,
@@ -283,19 +298,17 @@ export function useConflictDetection() {
requirements.push(requirement) requirements.push(requirement)
} else { } else {
console.warn( console.warn(
`[ConflictDetection] No Registry data found for ${packageName}, using fallback` `[ConflictDetection] No Registry data found for ${packageId}, using fallback`
) )
// Create fallback requirement without Registry data // Create fallback requirement without Registry data
const fallbackRequirement: NodePackRequirements = { const fallbackRequirement: NodePackRequirements = {
package_id: packageName, package_id: packageId,
package_name: packageName, package_name: pack.name || packageId,
installed_version: typedNodeInfo.ver || 'unknown', installed_version: pack.latest_version?.version || 'unknown',
is_enabled: typedNodeInfo.enabled, is_enabled: isEnabled,
is_banned: !typedNodeInfo.enabled, is_banned: !isEnabled,
ban_reason: !typedNodeInfo.enabled ban_reason: !isEnabled ? 'Package is disabled locally' : undefined,
? 'Package is disabled locally'
: undefined,
registry_fetch_time: new Date().toISOString(), registry_fetch_time: new Date().toISOString(),
has_registry_data: false has_registry_data: false
} }
@@ -415,13 +428,15 @@ export function useConflictDetection() {
try { try {
const comfyManagerService = useComfyManagerService() const comfyManagerService = useComfyManagerService()
// Get installed packages first // Use installed packs from useInstalledPacks composable
const installedPacks = await comfyManagerService.listInstalledPacks( if (
abortController.value?.signal !installedPacksReady.value ||
) !installedPacks.value ||
installedPacks.value.length === 0
if (!installedPacks) { ) {
console.warn('[ConflictDetection] No installed packages found') console.warn(
'[ConflictDetection] No installed packages available from useInstalledPacks'
)
return {} return {}
} }
@@ -429,27 +444,27 @@ export function useConflictDetection() {
// Check each installed package for import failures // Check each installed package for import failures
// Process in smaller batches to avoid overwhelming the API // Process in smaller batches to avoid overwhelming the API
const packageNames = Object.keys(installedPacks) const packageIds = installedPacks.value.map((pack) => pack.id)
const batchSize = 10 const batchSize = 10
for (let i = 0; i < packageNames.length; i += batchSize) { for (let i = 0; i < packageIds.length; i += batchSize) {
const batch = packageNames.slice(i, i + batchSize) const batch = packageIds.slice(i, i + batchSize)
const batchResults = await Promise.allSettled( const batchResults = await Promise.allSettled(
batch.map(async (packageName) => { batch.map(async (packageId) => {
try { try {
// Try to get import failure info for this package // Try to get import failure info for this package using normalized ID
const failInfo = await comfyManagerService.getImportFailInfo( const failInfo = await comfyManagerService.getImportFailInfo(
{ cnr_id: packageName }, { cnr_id: packageId },
abortController.value?.signal abortController.value?.signal
) )
if (failInfo) { if (failInfo) {
console.log( console.log(
`[ConflictDetection] Import failure found for ${packageName}:`, `[ConflictDetection] Import failure found for ${packageId}:`,
failInfo failInfo
) )
return { packageName, failInfo } return { packageId, failInfo }
} }
} catch (error) { } catch (error) {
// If API returns 400, it means no import failure info available // If API returns 400, it means no import failure info available
@@ -462,7 +477,7 @@ export function useConflictDetection() {
} }
console.warn( console.warn(
`[ConflictDetection] Failed to check import failure for ${packageName}:`, `[ConflictDetection] Failed to check import failure for ${packageId}:`,
error error
) )
} }
@@ -473,8 +488,8 @@ export function useConflictDetection() {
// Process batch results // Process batch results
batchResults.forEach((result) => { batchResults.forEach((result) => {
if (result.status === 'fulfilled' && result.value) { if (result.status === 'fulfilled' && result.value) {
const { packageName, failInfo } = result.value const { packageId, failInfo } = result.value
importFailures[packageName] = failInfo importFailures[packageId || ''] = failInfo
} }
}) })
} }
@@ -504,7 +519,7 @@ export function useConflictDetection() {
} }
// Process import failures // Process import failures
for (const [packageName, failureInfo] of Object.entries(importFailInfo)) { for (const [packageId, failureInfo] of Object.entries(importFailInfo)) {
if (failureInfo && typeof failureInfo === 'object') { if (failureInfo && typeof failureInfo === 'object') {
// Extract error information from Manager API response // Extract error information from Manager API response
const errorMsg = failureInfo.msg || 'Unknown import error' const errorMsg = failureInfo.msg || 'Unknown import error'
@@ -522,15 +537,15 @@ export function useConflictDetection() {
] ]
results.push({ results.push({
package_id: packageName, package_id: packageId,
package_name: packageName, package_name: packageId,
has_conflict: true, has_conflict: true,
conflicts, conflicts,
is_compatible: false is_compatible: false
}) })
console.warn( console.warn(
`[ConflictDetection] Python import failure detected for ${packageName}:`, `[ConflictDetection] Python import failure detected for ${packageId}:`,
{ {
path: modulePath, path: modulePath,
error: errorMsg, error: errorMsg,
@@ -949,11 +964,14 @@ function mergeConflictsByPackageName(
const mergedMap = new Map<string, ConflictDetectionResult>() const mergedMap = new Map<string, ConflictDetectionResult>()
conflicts.forEach((conflict) => { conflicts.forEach((conflict) => {
const packageName = conflict.package_name // Normalize package name by removing version suffix (@1_0_3) for consistent merging
const normalizedPackageName = conflict.package_name.includes('@')
? conflict.package_name.substring(0, conflict.package_name.indexOf('@'))
: conflict.package_name
if (mergedMap.has(packageName)) { if (mergedMap.has(normalizedPackageName)) {
// Package already exists, merge conflicts // Package already exists, merge conflicts
const existing = mergedMap.get(packageName)! const existing = mergedMap.get(normalizedPackageName)!
// Combine all conflicts, avoiding duplicates using lodash uniqBy for O(n) performance // Combine all conflicts, avoiding duplicates using lodash uniqBy for O(n) performance
const allConflicts = [...existing.conflicts, ...conflict.conflicts] const allConflicts = [...existing.conflicts, ...conflict.conflicts]
@@ -963,16 +981,20 @@ function mergeConflictsByPackageName(
`${conflict.type}|${conflict.current_value}|${conflict.required_value}` `${conflict.type}|${conflict.current_value}|${conflict.required_value}`
) )
// Update the existing entry // Update the existing entry with normalized package name
mergedMap.set(packageName, { mergedMap.set(normalizedPackageName, {
...existing, ...existing,
package_name: normalizedPackageName,
conflicts: uniqueConflicts, conflicts: uniqueConflicts,
has_conflict: uniqueConflicts.length > 0, has_conflict: uniqueConflicts.length > 0,
is_compatible: uniqueConflicts.length === 0 is_compatible: uniqueConflicts.length === 0
}) })
} else { } else {
// New package, add as-is // New package, add with normalized package name
mergedMap.set(packageName, conflict) mergedMap.set(normalizedPackageName, {
...conflict,
package_name: normalizedPackageName
})
} }
}) })

View File

@@ -14,13 +14,6 @@ import type { SettingParams } from '@/types/settingTypes'
* when they are no longer needed. * when they are no longer needed.
*/ */
export const CORE_SETTINGS: SettingParams[] = [ export const CORE_SETTINGS: SettingParams[] = [
{
id: 'Comfy.Memory.AllowManualUnload',
name: 'Allow manual unload of models and execution cache via user command',
type: 'hidden',
defaultValue: true,
versionAdded: '1.18.0'
},
{ {
id: 'Comfy.Validation.Workflows', id: 'Comfy.Validation.Workflows',
name: 'Validate workflows', name: 'Validate workflows',

View File

@@ -16,7 +16,7 @@ export const useConflictDetectionStore = defineStore(
conflictedPackages.value.some((pkg) => pkg.has_conflict) conflictedPackages.value.some((pkg) => pkg.has_conflict)
) )
const getConflictsForPackage = computed( const getConflictsForPackageByID = computed(
() => (packageId: string) => () => (packageId: string) =>
conflictedPackages.value.find((pkg) => pkg.package_id === packageId) conflictedPackages.value.find((pkg) => pkg.package_id === packageId)
) )
@@ -57,7 +57,7 @@ export const useConflictDetectionStore = defineStore(
lastDetectionTime, lastDetectionTime,
// Getters // Getters
hasConflicts, hasConflicts,
getConflictsForPackage, getConflictsForPackageByID,
bannedPackages, bannedPackages,
securityPendingPackages, securityPendingPackages,
// Actions // Actions

View File

@@ -83,12 +83,12 @@ describe('useConflictDetectionStore', () => {
}) })
}) })
describe('getConflictsForPackage', () => { describe('getConflictsForPackageByID', () => {
it('should find package by exact ID match', () => { it('should find package by exact ID match', () => {
const store = useConflictDetectionStore() const store = useConflictDetectionStore()
store.setConflictedPackages(mockConflictedPackages) store.setConflictedPackages(mockConflictedPackages)
const result = store.getConflictsForPackage('ComfyUI-Manager') const result = store.getConflictsForPackageByID('ComfyUI-Manager')
expect(result).toBeDefined() expect(result).toBeDefined()
expect(result?.package_id).toBe('ComfyUI-Manager') expect(result?.package_id).toBe('ComfyUI-Manager')
@@ -99,7 +99,7 @@ describe('useConflictDetectionStore', () => {
const store = useConflictDetectionStore() const store = useConflictDetectionStore()
store.setConflictedPackages(mockConflictedPackages) store.setConflictedPackages(mockConflictedPackages)
const result = store.getConflictsForPackage('non-existent-package') const result = store.getConflictsForPackageByID('non-existent-package')
expect(result).toBeUndefined() expect(result).toBeUndefined()
}) })