mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-15 11:44:10 +00:00
Current `main` **fails a fresh `knip` run** with 13 unused exported types (exit 1). They're invisible on main because lint/knip only runs on `pull_request`/`merge_group`, never on push to main — so merge skew (one PR adds an export used by file X; a later PR removes X's usage) accumulates latent failures that ambush backport branches (e.g. #13163, #13162). Each of the 13 is `export`ed but referenced only within its own file (verified 0 importers; ≥2 in-file uses, so not dead code). Fix: drop the redundant `export`. Types cleaned: `VideoSource`, `ObjectInfoResponse`, `PromotedMissingModelWorkflow`, `PixelReadout`, `ResizeDirection`, `ResizeHandle`, `RunButtonTelemetryOptions`, `ResolvedModelNode`, `AccountPreconditionContext`, `SubscriptionDialogOptions`, `MonthlyCreditsUsage`, `MissingMediaReference`, `ResolvedHostWidget`. Reviewer note: `ResolvedHostWidget` and `ResolvedModelNode` sit under `renderer/extensions`/`platform/assets`; no in-repo importers, but if either is intended as published/extension-facing API, prefer a knip `entry`/`ignore` over un-exporting — flag in review and I'll adjust. After fresh `knip`: **0 unused exported types**. Supersedes #13179 (fixed only `AccountPreconditionContext`). Pairs with the push-gate workflow #13203 — merge this first so that gate is green on main. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
import { assetItemSchema } from '@/platform/assets/schemas/assetSchema'
|
|
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
|
import {
|
|
MISSING_TAG,
|
|
MODELS_TAG
|
|
} from '@/platform/assets/services/assetService'
|
|
import { getAssetFilename } from '@/platform/assets/utils/assetMetadataUtils'
|
|
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
|
|
import type { ModelNodeProvider } from '@/stores/modelToNodeStore'
|
|
|
|
type ResolveErrorCode = 'INVALID_ASSET' | 'NO_PROVIDER'
|
|
|
|
export interface ResolveModelNodeError {
|
|
code: ResolveErrorCode
|
|
message: string
|
|
assetId: string
|
|
details?: Record<string, unknown>
|
|
}
|
|
|
|
interface ResolvedModelNode {
|
|
provider: ModelNodeProvider
|
|
filename: string
|
|
}
|
|
|
|
type Result<T, E> = { success: true; value: T } | { success: false; error: E }
|
|
|
|
/**
|
|
* Resolves an asset item to the node provider and filename needed to add a
|
|
* model loader node. Validation failures return error results rather than
|
|
* throwing, so callers can degrade gracefully in UI contexts.
|
|
*/
|
|
export function resolveModelNodeFromAsset(
|
|
asset: AssetItem
|
|
): Result<ResolvedModelNode, ResolveModelNodeError> {
|
|
const validatedAsset = assetItemSchema.safeParse(asset)
|
|
|
|
if (!validatedAsset.success) {
|
|
const errorMessage = validatedAsset.error.errors
|
|
.map((e) => `${e.path.join('.')}: ${e.message}`)
|
|
.join(', ')
|
|
console.error('Invalid asset item:', errorMessage)
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: 'INVALID_ASSET',
|
|
message: 'Asset schema validation failed',
|
|
assetId: typeof asset?.id === 'string' ? asset.id : 'unknown',
|
|
details: { validationErrors: errorMessage }
|
|
}
|
|
}
|
|
}
|
|
|
|
const validAsset = validatedAsset.data
|
|
|
|
const filename = getAssetFilename(validAsset)
|
|
if (filename.length === 0) {
|
|
console.error(
|
|
`Asset ${validAsset.id} has invalid user_metadata.filename (expected non-empty string, got ${typeof filename})`
|
|
)
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: 'INVALID_ASSET',
|
|
message: `Invalid filename (expected non-empty string, got ${typeof filename})`,
|
|
assetId: validAsset.id
|
|
}
|
|
}
|
|
}
|
|
|
|
if (validAsset.tags.length === 0) {
|
|
console.error(
|
|
`Asset ${validAsset.id} has no tags defined (expected at least one category tag)`
|
|
)
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: 'INVALID_ASSET',
|
|
message: 'Asset has no tags defined',
|
|
assetId: validAsset.id
|
|
}
|
|
}
|
|
}
|
|
|
|
const category = validAsset.tags.find(
|
|
(tag) => tag !== MODELS_TAG && tag !== MISSING_TAG
|
|
)
|
|
if (!category) {
|
|
console.error(
|
|
`Asset ${validAsset.id} has no valid category tag. Available tags: ${validAsset.tags.join(', ')} (expected tag other than '${MODELS_TAG}' or '${MISSING_TAG}')`
|
|
)
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: 'INVALID_ASSET',
|
|
message: 'Asset has no valid category tag',
|
|
assetId: validAsset.id,
|
|
details: { availableTags: validAsset.tags }
|
|
}
|
|
}
|
|
}
|
|
|
|
const provider = useModelToNodeStore().getNodeProvider(category)
|
|
if (!provider) {
|
|
console.error(`No node provider registered for category: ${category}`)
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: 'NO_PROVIDER',
|
|
message: `No node provider registered for category: ${category}`,
|
|
assetId: validAsset.id,
|
|
details: { category }
|
|
}
|
|
}
|
|
}
|
|
|
|
return { success: true, value: { provider, filename } }
|
|
}
|