fix: properly type extractWorkflow return (#7646)

## Summary
Type `extractWorkflow` return as `ComfyWorkflowJSON | undefined` instead
of `unknown` for better type safety downstream.

## Context
This is a small preparatory PR to slim down the Jobs API migration PR
(PR 2 of 3).

## Test plan
- [x] TypeCheck passes
- [x] Lint passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7646-fix-properly-type-extractWorkflow-return-2ce6d73d365081c794eac3669632271f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
ric-yu
2026-01-13 20:17:28 -08:00
committed by GitHub
parent ebca0cb1e0
commit 773f5f5cd9
2 changed files with 58 additions and 12 deletions

View File

@@ -257,35 +257,66 @@ describe('fetchJobs', () => {
})
describe('extractWorkflow', () => {
it('extracts workflow from nested structure', () => {
const validWorkflow = {
version: 0.4,
last_node_id: 1,
last_link_id: 0,
nodes: [],
links: []
}
it('extracts and validates workflow from nested structure', async () => {
const jobDetail = {
...createMockJob('job1', 'completed'),
workflow: {
extra_data: {
extra_pnginfo: {
workflow: { nodes: [], links: [] }
workflow: validWorkflow
}
}
}
}
const workflow = extractWorkflow(jobDetail)
const workflow = await extractWorkflow(jobDetail)
expect(workflow).toEqual({ nodes: [], links: [] })
expect(workflow).toEqual(validWorkflow)
})
it('returns undefined if workflow not present', () => {
it('returns undefined if workflow not present', async () => {
const jobDetail = createMockJob('job1', 'completed')
const workflow = extractWorkflow(jobDetail)
const workflow = await extractWorkflow(jobDetail)
expect(workflow).toBeUndefined()
})
it('returns undefined for undefined input', () => {
const workflow = extractWorkflow(undefined)
it('returns undefined for undefined input', async () => {
const workflow = await extractWorkflow(undefined)
expect(workflow).toBeUndefined()
})
it('returns undefined for invalid workflow and logs warning', async () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const jobDetail = {
...createMockJob('job1', 'completed'),
workflow: {
extra_data: {
extra_pnginfo: {
workflow: { invalid: 'data' }
}
}
}
}
const workflow = await extractWorkflow(jobDetail)
expect(workflow).toBeUndefined()
expect(consoleSpy).toHaveBeenCalledWith(
'[extractWorkflow] Workflow validation failed:',
expect.any(String)
)
consoleSpy.mockRestore()
})
})
})

View File

@@ -6,6 +6,8 @@
* All distributions use the /jobs endpoint.
*/
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
import { validateComfyWorkflow } from '@/platform/workflow/validation/schemas/workflowSchema'
import type { PromptId } from '@/schemas/apiSchema'
import type {
@@ -135,12 +137,25 @@ export async function fetchJobDetail(
}
/**
* Extracts workflow from job detail response.
* Extracts and validates workflow from job detail response.
* The workflow is nested at: workflow.extra_data.extra_pnginfo.workflow
* Full workflow validation happens downstream via validateComfyWorkflow.
*
* Uses Zod validation via validateComfyWorkflow to ensure the workflow
* conforms to the expected schema. Logs validation failures for debugging
* but still returns undefined to allow graceful degradation.
*/
export function extractWorkflow(job: JobDetail | undefined): unknown {
export async function extractWorkflow(
job: JobDetail | undefined
): Promise<ComfyWorkflowJSON | undefined> {
const parsed = zWorkflowContainer.safeParse(job?.workflow)
if (!parsed.success) return undefined
return parsed.data.extra_data?.extra_pnginfo?.workflow
const rawWorkflow = parsed.data.extra_data?.extra_pnginfo?.workflow
if (!rawWorkflow) return undefined
const validated = await validateComfyWorkflow(rawWorkflow, (error) => {
console.warn('[extractWorkflow] Workflow validation failed:', error)
})
return validated ?? undefined
}