fix: accept items with filename but no subfolder in isResultItem

Restores compatibility with custom nodes that only send filename without
subfolder. The ResultItemImpl constructor already falls back to ''.

Addresses review feedback:
https://github.com/Comfy-Org/ComfyUI_frontend/pull/9622#discussion_r2925170216
This commit is contained in:
bymyself
2026-03-12 08:00:02 -07:00
parent 85c6740928
commit 7535857276
3 changed files with 37 additions and 10 deletions

View File

@@ -120,11 +120,26 @@ describe(flattenNodeOutput, () => {
expect(result[0].mediaType).toBe('images')
})
it('excludes partial ResultItem objects missing required fields', () => {
it('accepts items with filename but no subfolder', () => {
const output = {
images: [
{ filename: 'valid.png', subfolder: '', type: 'output' },
{ filename: 'no-subfolder.png' }
]
} as unknown as NodeExecutionOutput
const result = flattenNodeOutput(['1', output])
expect(result).toHaveLength(2)
expect(result[0].filename).toBe('valid.png')
expect(result[1].filename).toBe('no-subfolder.png')
expect(result[1].subfolder).toBe('')
})
it('excludes items missing filename', () => {
const output = {
images: [
{ filename: 'valid.png', subfolder: '', type: 'output' },
{ filename: 'no-subfolder.png' },
{ subfolder: '', type: 'output' }
]
} as unknown as NodeExecutionOutput

View File

@@ -119,11 +119,26 @@ describe(parseNodeOutput, () => {
expect(result[0].mediaType).toBe('images')
})
it('excludes partial ResultItem objects missing required fields', () => {
it('accepts items with filename but no subfolder', () => {
const output = {
images: [
{ filename: 'valid.png', subfolder: '', type: 'output' },
{ filename: 'no-subfolder.png' }
]
} as unknown as NodeExecutionOutput
const result = parseNodeOutput('1', output)
expect(result).toHaveLength(2)
expect(result[0].filename).toBe('valid.png')
expect(result[1].filename).toBe('no-subfolder.png')
expect(result[1].subfolder).toBe('')
})
it('excludes items missing filename', () => {
const output = {
images: [
{ filename: 'valid.png', subfolder: '', type: 'output' },
{ filename: 'no-subfolder.png' },
{ subfolder: '', type: 'output' }
]
} as unknown as NodeExecutionOutput

View File

@@ -5,12 +5,10 @@ import { ResultItemImpl } from '@/stores/queueStore'
const METADATA_KEYS = new Set(['animated', 'text'])
/**
* Validates that an unknown value is a well-formed ResultItem with required
* fields for constructing a previewable output.
* Validates that an unknown value is a well-formed ResultItem.
*
* Stricter than `zResultItem.safeParse()` because the Zod schema marks
* `filename` and `subfolder` as optional (matching the wire format), but
* a ResultItemImpl needs both to construct a valid URL.
* Requires `filename` (string) since ResultItemImpl needs it for a valid URL.
* `subfolder` is optional here — ResultItemImpl constructor falls back to ''.
*/
function isResultItem(item: unknown): item is ResultItem {
if (!item || typeof item !== 'object' || Array.isArray(item)) return false
@@ -18,7 +16,6 @@ function isResultItem(item: unknown): item is ResultItem {
const candidate = item as Record<string, unknown>
if (typeof candidate.filename !== 'string') return false
if (typeof candidate.subfolder !== 'string') return false
if (
candidate.type !== undefined &&