mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 00:50:05 +00:00
[feat] add asset metadata validation utilities
This commit is contained in:
@@ -3,6 +3,10 @@ import { computed, ref } from 'vue'
|
||||
import { t } from '@/i18n'
|
||||
import type { UUID } from '@/lib/litegraph/src/utils/uuid'
|
||||
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
import {
|
||||
getAssetBaseModel,
|
||||
getAssetDescription
|
||||
} from '@/platform/assets/utils/assetMetadataUtils'
|
||||
import { formatSize } from '@/utils/formatUtil'
|
||||
|
||||
type AssetBadge = {
|
||||
@@ -37,7 +41,7 @@ export function useAssetBrowser(assets: AssetItem[] = []) {
|
||||
// Extract description from metadata or create from tags
|
||||
const typeTag = asset.tags.find((tag) => tag !== 'models')
|
||||
const description =
|
||||
asset.user_metadata?.description ||
|
||||
getAssetDescription(asset) ||
|
||||
`${typeTag || t('assetBrowser.unknown')} model`
|
||||
|
||||
// Format file size
|
||||
@@ -52,9 +56,10 @@ export function useAssetBrowser(assets: AssetItem[] = []) {
|
||||
}
|
||||
|
||||
// Base model badge from metadata
|
||||
if (asset.user_metadata?.base_model) {
|
||||
const baseModel = getAssetBaseModel(asset)
|
||||
if (baseModel) {
|
||||
badges.push({
|
||||
label: asset.user_metadata.base_model,
|
||||
label: baseModel,
|
||||
type: 'base'
|
||||
})
|
||||
}
|
||||
@@ -126,9 +131,10 @@ export function useAssetBrowser(assets: AssetItem[] = []) {
|
||||
const filterByQuery = (query: string) => (asset: AssetItem) => {
|
||||
if (!query) return true
|
||||
const lowerQuery = query.toLowerCase()
|
||||
const description = getAssetDescription(asset)
|
||||
return (
|
||||
asset.name.toLowerCase().includes(lowerQuery) ||
|
||||
asset.user_metadata?.description?.toLowerCase().includes(lowerQuery) ||
|
||||
(description && description.toLowerCase().includes(lowerQuery)) ||
|
||||
asset.tags.some((tag) => tag.toLowerCase().includes(lowerQuery))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const zAsset = z.object({
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
last_access_time: z.string(),
|
||||
user_metadata: z.record(z.any()).optional(),
|
||||
user_metadata: z.record(z.unknown()).optional(), // API allows arbitrary key-value pairs
|
||||
preview_id: z.string().nullable().optional()
|
||||
})
|
||||
|
||||
|
||||
27
src/platform/assets/utils/assetMetadataUtils.ts
Normal file
27
src/platform/assets/utils/assetMetadataUtils.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
|
||||
/**
|
||||
* Type-safe utilities for extracting metadata from assets
|
||||
*/
|
||||
|
||||
/**
|
||||
* Safely extracts string description from asset metadata
|
||||
* @param asset - The asset to extract description from
|
||||
* @returns The description string or null if not present/not a string
|
||||
*/
|
||||
export function getAssetDescription(asset: AssetItem): string | null {
|
||||
return typeof asset.user_metadata?.description === 'string'
|
||||
? asset.user_metadata.description
|
||||
: null
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely extracts string base_model from asset metadata
|
||||
* @param asset - The asset to extract base_model from
|
||||
* @returns The base_model string or null if not present/not a string
|
||||
*/
|
||||
export function getAssetBaseModel(asset: AssetItem): string | null {
|
||||
return typeof asset.user_metadata?.base_model === 'string'
|
||||
? asset.user_metadata.base_model
|
||||
: null
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||
import {
|
||||
getAssetBaseModel,
|
||||
getAssetDescription
|
||||
} from '@/platform/assets/utils/assetMetadataUtils'
|
||||
|
||||
describe('assetMetadataUtils', () => {
|
||||
const mockAsset: AssetItem = {
|
||||
id: 'test-id',
|
||||
name: 'test-model',
|
||||
asset_hash: 'hash123',
|
||||
size: 1024,
|
||||
mime_type: 'application/octet-stream',
|
||||
tags: ['models', 'checkpoints'],
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
last_access_time: '2024-01-01T00:00:00Z'
|
||||
}
|
||||
|
||||
describe('getAssetDescription', () => {
|
||||
it('should return string description when present', () => {
|
||||
const asset = {
|
||||
...mockAsset,
|
||||
user_metadata: { description: 'A test model' }
|
||||
}
|
||||
expect(getAssetDescription(asset)).toBe('A test model')
|
||||
})
|
||||
|
||||
it('should return null when description is not a string', () => {
|
||||
const asset = {
|
||||
...mockAsset,
|
||||
user_metadata: { description: 123 }
|
||||
}
|
||||
expect(getAssetDescription(asset)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null when no metadata', () => {
|
||||
expect(getAssetDescription(mockAsset)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAssetBaseModel', () => {
|
||||
it('should return string base_model when present', () => {
|
||||
const asset = {
|
||||
...mockAsset,
|
||||
user_metadata: { base_model: 'SDXL' }
|
||||
}
|
||||
expect(getAssetBaseModel(asset)).toBe('SDXL')
|
||||
})
|
||||
|
||||
it('should return null when base_model is not a string', () => {
|
||||
const asset = {
|
||||
...mockAsset,
|
||||
user_metadata: { base_model: 123 }
|
||||
}
|
||||
expect(getAssetBaseModel(asset)).toBeNull()
|
||||
})
|
||||
|
||||
it('should return null when no metadata', () => {
|
||||
expect(getAssetBaseModel(mockAsset)).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user