fix(types): add null guards to browser_tests fixtures

This commit is contained in:
DrJKL
2026-01-12 10:17:53 -08:00
parent 1b4dd57d32
commit eb2c4e29a3
5 changed files with 237 additions and 112 deletions

View File

@@ -81,11 +81,14 @@ class ComfyMenu {
await this.themeToggleButton.click()
await this.page.evaluate(() => {
return new Promise((resolve) => {
window['app'].ui.settings.addEventListener(
'Comfy.ColorPalette.change',
resolve,
{ once: true }
)
const app = window.app
if (!app) {
resolve(undefined)
return
}
app.ui.settings.addEventListener('Comfy.ColorPalette.change', resolve, {
once: true
})
setTimeout(resolve, 5000)
})
@@ -94,9 +97,9 @@ class ComfyMenu {
async getThemeId() {
return await this.page.evaluate(async () => {
return await window['app'].ui.settings.getSettingValue(
'Comfy.ColorPalette'
)
const app = window.app
if (!app) return undefined
return await app.ui.settings.getSettingValue('Comfy.ColorPalette')
})
}
}
@@ -138,7 +141,14 @@ class ConfirmDialog {
// Wait for workflow service to finish if it's busy
await this.page.waitForFunction(
() => window['app']?.extensionManager?.workflow?.isBusy === false,
() => {
const app = window.app
if (!app) return true
const extMgr = app.extensionManager as {
workflow?: { isBusy?: boolean }
}
return extMgr.workflow?.isBusy === false
},
undefined,
{ timeout: 3000 }
)
@@ -256,7 +266,12 @@ export class ComfyPage {
}
await this.page.evaluate(async () => {
await window['app'].extensionManager.workflow.syncWorkflows()
const app = window.app
if (!app) return
const extMgr = app.extensionManager as {
workflow?: { syncWorkflows: () => Promise<void> }
}
if (extMgr.workflow) await extMgr.workflow.syncWorkflows()
})
// Wait for Vue to re-render the workflow list
@@ -360,7 +375,9 @@ export class ComfyPage {
async executeCommand(commandId: string) {
await this.page.evaluate((id: string) => {
return window['app'].extensionManager.command.execute(id)
const app = window.app
if (!app) return
return app.extensionManager.command.execute(id)
}, commandId)
}
@@ -370,7 +387,8 @@ export class ComfyPage {
) {
await this.page.evaluate(
({ commandId, commandStr }) => {
const app = window['app']
const app = window.app
if (!app) return
const randomSuffix = Math.random().toString(36).substring(2, 8)
const extensionName = `TestExtension_${randomSuffix}`
@@ -391,7 +409,8 @@ export class ComfyPage {
async registerKeybinding(keyCombo: KeyCombo, command: () => void) {
await this.page.evaluate(
({ keyCombo, commandStr }) => {
const app = window['app']
const app = window.app
if (!app) return
const randomSuffix = Math.random().toString(36).substring(2, 8)
const extensionName = `TestExtension_${randomSuffix}`
const commandId = `TestCommand_${randomSuffix}`
@@ -419,7 +438,9 @@ export class ComfyPage {
async setSetting(settingId: string, settingValue: any) {
return await this.page.evaluate(
async ({ id, value }) => {
await window['app'].extensionManager.setting.set(id, value)
const app = window.app
if (!app) return
await app.extensionManager.setting.set(id, value)
},
{ id: settingId, value: settingValue }
)
@@ -427,7 +448,9 @@ export class ComfyPage {
async getSetting(settingId: string) {
return await this.page.evaluate(async (id) => {
return await window['app'].extensionManager.setting.get(id)
const app = window.app
if (!app) return undefined
return await app.extensionManager.setting.get(id)
}, settingId)
}
@@ -873,8 +896,10 @@ export class ComfyPage {
const foundSlot = await this.page.evaluate(
async (params) => {
const { slotType, action, targetSlotName } = params
const app = window['app']
const app = window.app
if (!app) throw new Error('App not initialized')
const currentGraph = app.canvas.graph
if (!currentGraph) throw new Error('No graph available')
// Check if we're in a subgraph
if (currentGraph.constructor.name !== 'Subgraph') {
@@ -883,13 +908,24 @@ export class ComfyPage {
)
}
// Get the appropriate node and slots
// Get the appropriate node and slots (these are Subgraph-specific properties)
const subgraph = currentGraph as {
inputNode?: { onPointerDown?: (...args: unknown[]) => void }
outputNode?: { onPointerDown?: (...args: unknown[]) => void }
inputs?: Array<{
name: string
pos?: number[]
boundingRect?: number[]
}>
outputs?: Array<{
name: string
pos?: number[]
boundingRect?: number[]
}>
}
const node =
slotType === 'input'
? currentGraph.inputNode
: currentGraph.outputNode
const slots =
slotType === 'input' ? currentGraph.inputs : currentGraph.outputs
slotType === 'input' ? subgraph.inputNode : subgraph.outputNode
const slots = slotType === 'input' ? subgraph.inputs : subgraph.outputs
if (!node) {
throw new Error(`No ${slotType} node found in subgraph`)
@@ -970,6 +1006,7 @@ export class ComfyPage {
}
if (node.onPointerDown) {
// Call onPointerDown for test simulation
node.onPointerDown(
event,
app.canvas.pointer,
@@ -977,8 +1014,11 @@ export class ComfyPage {
)
// Trigger double-click
if (app.canvas.pointer.onDoubleClick) {
app.canvas.pointer.onDoubleClick(event)
const onDoubleClick = app.canvas.pointer.onDoubleClick as
| ((e: unknown) => void)
| undefined
if (onDoubleClick) {
onDoubleClick(event)
}
}
@@ -1574,7 +1614,9 @@ export class ComfyPage {
async convertOffsetToCanvas(pos: [number, number]) {
return this.page.evaluate((pos) => {
return window['app'].canvas.ds.convertOffsetToCanvas(pos)
const app = window.app
if (!app) return pos
return app.canvas.ds.convertOffsetToCanvas(pos)
}, pos)
}
@@ -1588,14 +1630,18 @@ export class ComfyPage {
}
async getNodes(): Promise<LGraphNode[]> {
return await this.page.evaluate(() => {
return window['app'].graph.nodes
const app = window.app
if (!app?.graph?.nodes) return []
return app.graph.nodes
})
}
async getNodeRefsByType(type: string): Promise<NodeReference[]> {
return Promise.all(
(
await this.page.evaluate((type) => {
return window['app'].graph.nodes
const app = window.app
if (!app?.graph?.nodes) return []
return app.graph.nodes
.filter((n: LGraphNode) => n.type === type)
.map((n: LGraphNode) => n.id)
}, type)
@@ -1606,7 +1652,9 @@ export class ComfyPage {
return Promise.all(
(
await this.page.evaluate((title) => {
return window['app'].graph.nodes
const app = window.app
if (!app?.graph?.nodes) return []
return app.graph.nodes
.filter((n: LGraphNode) => n.title === title)
.map((n: LGraphNode) => n.id)
}, title)
@@ -1616,7 +1664,9 @@ export class ComfyPage {
async getFirstNodeRef(): Promise<NodeReference | null> {
const id = await this.page.evaluate(() => {
return window['app'].graph.nodes[0]?.id
const app = window.app
if (!app?.graph?.nodes) return undefined
return app.graph.nodes[0]?.id
})
if (!id) return null
return this.getNodeRefById(id)
@@ -1626,32 +1676,41 @@ export class ComfyPage {
}
async getUndoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.undoQueue.length
const app = window.app
if (!app) return 0
const extMgr = app.extensionManager as WorkspaceStore
return extMgr.workflow.activeWorkflow?.changeTracker.undoQueue.length ?? 0
})
}
async getRedoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.redoQueue.length
const app = window.app
if (!app) return 0
const extMgr = app.extensionManager as WorkspaceStore
return extMgr.workflow.activeWorkflow?.changeTracker.redoQueue.length ?? 0
})
}
async isCurrentWorkflowModified() {
return this.page.evaluate(() => {
return (window['app'].extensionManager as WorkspaceStore).workflow
.activeWorkflow?.isModified
const app = window.app
if (!app) return false
const extMgr = app.extensionManager as WorkspaceStore
return extMgr.workflow.activeWorkflow?.isModified ?? false
})
}
async getExportedWorkflow({ api = false }: { api?: boolean } = {}) {
return this.page.evaluate(async (api) => {
return (await window['app'].graphToPrompt())[api ? 'output' : 'workflow']
const app = window.app
if (!app) return undefined
return (await app.graphToPrompt())[api ? 'output' : 'workflow']
}, api)
}
async setFocusMode(focusMode: boolean) {
await this.page.evaluate((focusMode) => {
window['app'].extensionManager.focusMode = focusMode
const app = window.app
if (!app) return
const extMgr = app.extensionManager as { focusMode?: boolean }
extMgr.focusMode = focusMode
}, focusMode)
await this.nextFrame()
}
@@ -1664,7 +1723,9 @@ export class ComfyPage {
*/
async getGroupPosition(title: string): Promise<Position> {
const pos = await this.page.evaluate((title) => {
const groups = window['app'].graph.groups
const app = window.app
if (!app?.graph?.groups) return null
const groups = app.graph.groups
const group = groups.find((g: { title: string }) => g.title === title)
if (!group) return null
return { x: group.pos[0], y: group.pos[1] }
@@ -1686,7 +1747,8 @@ export class ComfyPage {
}): Promise<void> {
const { name, deltaX, deltaY } = options
const screenPos = await this.page.evaluate((title) => {
const app = window['app']
const app = window.app
if (!app?.graph?.groups) return null
const groups = app.graph.groups
const group = groups.find((g: { title: string }) => g.title === title)
if (!group) return null
@@ -1754,11 +1816,16 @@ export const comfyPageFixture = base.extend<{
}
})
interface MatcherContext {
isNot: boolean
}
const makeMatcher = function <T>(
getValue: (node: NodeReference) => Promise<T> | T,
type: string
) {
return async function (
this: MatcherContext,
node: NodeReference,
options?: { timeout?: number; intervals?: number[] }
) {
@@ -1784,7 +1851,11 @@ export const comfyExpect = expect.extend({
toBePinned: makeMatcher((n) => n.isPinned(), 'pinned'),
toBeBypassed: makeMatcher((n) => n.isBypassed(), 'bypassed'),
toBeCollapsed: makeMatcher((n) => n.isCollapsed(), 'collapsed'),
async toHaveFocus(locator: Locator, options = { timeout: 256 }) {
async toHaveFocus(
this: MatcherContext,
locator: Locator,
options = { timeout: 256 }
) {
const isFocused = await locator.evaluate(
(el) => el === document.activeElement
)

View File

@@ -31,7 +31,7 @@ class SidebarTab {
}
export class NodeLibrarySidebarTab extends SidebarTab {
constructor(public readonly page: Page) {
constructor(public override readonly page: Page) {
super(page, 'node-library')
}
@@ -55,12 +55,12 @@ export class NodeLibrarySidebarTab extends SidebarTab {
return this.tabContainer.locator('.new-folder-button')
}
async open() {
override async open() {
await super.open()
await this.nodeLibraryTree.waitFor({ state: 'visible' })
}
async close() {
override async close() {
if (!this.tabButton.isVisible()) {
return
}
@@ -87,7 +87,7 @@ export class NodeLibrarySidebarTab extends SidebarTab {
}
export class WorkflowsSidebarTab extends SidebarTab {
constructor(public readonly page: Page) {
constructor(public override readonly page: Page) {
super(page, 'workflows')
}
@@ -140,7 +140,14 @@ export class WorkflowsSidebarTab extends SidebarTab {
// Wait for workflow service to finish renaming
await this.page.waitForFunction(
() => !window['app']?.extensionManager?.workflow?.isBusy,
() => {
const app = window.app
if (!app) return true
const extMgr = app.extensionManager as {
workflow?: { isBusy?: boolean }
}
return !extMgr.workflow?.isBusy
},
undefined,
{ timeout: 3000 }
)

View File

@@ -86,7 +86,14 @@ export class Topbar {
// Wait for workflow service to finish saving
await this.page.waitForFunction(
() => !window['app'].extensionManager.workflow.isBusy,
() => {
const app = window.app
if (!app) return true
const extMgr = app.extensionManager as {
workflow?: { isBusy?: boolean }
}
return !extMgr.workflow?.isBusy
},
undefined,
{ timeout: 3000 }
)

View File

@@ -22,7 +22,10 @@ export class SubgraphSlotReference {
async getPosition(): Promise<Position> {
const pos: [number, number] = await this.comfyPage.page.evaluate(
([type, slotName]) => {
const currentGraph = window['app'].canvas.graph
const app = window.app
if (!app) throw new Error('App not initialized')
const currentGraph = app.canvas.graph
if (!currentGraph) throw new Error('No graph available')
// Check if we're in a subgraph
if (currentGraph.constructor.name !== 'Subgraph') {
@@ -31,15 +34,18 @@ export class SubgraphSlotReference {
)
}
const slots =
type === 'input' ? currentGraph.inputs : currentGraph.outputs
const subgraph = currentGraph as {
inputs?: Array<{ name: string; pos?: number[] }>
outputs?: Array<{ name: string; pos?: number[] }>
}
const slots = type === 'input' ? subgraph.inputs : subgraph.outputs
if (!slots || slots.length === 0) {
throw new Error(`No ${type} slots found in subgraph`)
}
// Find the specific slot or use the first one if no name specified
const slot = slotName
? slots.find((s) => s.name === slotName)
? slots.find((s: { name: string }) => s.name === slotName)
: slots[0]
if (!slot) {
@@ -51,7 +57,7 @@ export class SubgraphSlotReference {
}
// Convert from offset to canvas coordinates
const canvasPos = window['app'].canvas.ds.convertOffsetToCanvas([
const canvasPos = app.canvas.ds.convertOffsetToCanvas([
slot.pos[0],
slot.pos[1]
])
@@ -69,7 +75,10 @@ export class SubgraphSlotReference {
async getOpenSlotPosition(): Promise<Position> {
const pos: [number, number] = await this.comfyPage.page.evaluate(
([type]) => {
const currentGraph = window['app'].canvas.graph
const app = window.app
if (!app) throw new Error('App not initialized')
const currentGraph = app.canvas.graph
if (!currentGraph) throw new Error('No graph available')
if (currentGraph.constructor.name !== 'Subgraph') {
throw new Error(
@@ -77,35 +86,35 @@ export class SubgraphSlotReference {
)
}
const node =
type === 'input' ? currentGraph.inputNode : currentGraph.outputNode
const slots =
type === 'input' ? currentGraph.inputs : currentGraph.outputs
const subgraph = currentGraph as {
inputNode?: { pos: number[]; size: number[] }
outputNode?: { pos: number[]; size: number[] }
inputs?: Array<{ pos?: number[] }>
outputs?: Array<{ pos?: number[] }>
slotAnchorX?: number
}
const node = type === 'input' ? subgraph.inputNode : subgraph.outputNode
const slots = type === 'input' ? subgraph.inputs : subgraph.outputs
if (!node) {
throw new Error(`No ${type} node found in subgraph`)
}
// Calculate position for next available slot
// const nextSlotIndex = slots?.length || 0
// const slotHeight = 20
// const slotY = node.pos[1] + 30 + nextSlotIndex * slotHeight
// Find last slot position
const lastSlot = slots.at(-1)
const lastSlot = slots?.at(-1)
let slotX: number
let slotY: number
if (lastSlot) {
if (lastSlot?.pos) {
// If there are existing slots, position the new one below the last one
const gapHeight = 20
slotX = lastSlot.pos[0]
slotY = lastSlot.pos[1] + gapHeight
} else {
// No existing slots - use slotAnchorX if available, otherwise calculate from node position
if (currentGraph.slotAnchorX !== undefined) {
if (subgraph.slotAnchorX !== undefined) {
// The actual slot X position seems to be slotAnchorX - 10
slotX = currentGraph.slotAnchorX - 10
slotX = subgraph.slotAnchorX - 10
} else {
// Fallback: calculate from node edge
slotX =
@@ -118,10 +127,7 @@ export class SubgraphSlotReference {
}
// Convert from offset to canvas coordinates
const canvasPos = window['app'].canvas.ds.convertOffsetToCanvas([
slotX,
slotY
])
const canvasPos = app.canvas.ds.convertOffsetToCanvas([slotX, slotY])
return canvasPos
},
[this.type] as const
@@ -143,16 +149,18 @@ class NodeSlotReference {
async getPosition() {
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
([type, id, index]) => {
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const graph = app.canvas.graph
// Use canvas.graph to get the current graph (works in both main graph and subgraphs)
const node = window['app'].canvas.graph.getNodeById(id)
const node = graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
const rawPos = node.getConnectionPos(type === 'input', index)
const convertedPos =
window['app'].canvas.ds.convertOffsetToCanvas(rawPos)
const convertedPos = app.canvas.ds.convertOffsetToCanvas(rawPos)
// Debug logging - convert Float64Arrays to regular arrays for visibility
// eslint-disable-next-line no-console
console.log(
`NodeSlotReference debug for ${type} slot ${index} on node ${id}:`,
{
@@ -160,7 +168,7 @@ class NodeSlotReference {
nodeSize: [node.size[0], node.size[1]],
rawConnectionPos: [rawPos[0], rawPos[1]],
convertedPos: [convertedPos[0], convertedPos[1]],
currentGraphType: window['app'].canvas.graph.constructor.name
currentGraphType: graph.constructor.name
}
)
@@ -176,7 +184,9 @@ class NodeSlotReference {
async getLinkCount() {
return await this.node.comfyPage.page.evaluate(
([type, id, index]) => {
const node = window['app'].canvas.graph.getNodeById(id)
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const node = app.canvas.graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
if (type === 'input') {
return node.inputs[index].link == null ? 0 : 1
@@ -189,7 +199,9 @@ class NodeSlotReference {
async removeLinks() {
await this.node.comfyPage.page.evaluate(
([type, id, index]) => {
const node = window['app'].canvas.graph.getNodeById(id)
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const node = app.canvas.graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
if (type === 'input') {
node.disconnectInput(index)
@@ -214,15 +226,19 @@ class NodeWidgetReference {
async getPosition(): Promise<Position> {
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
([id, index]) => {
const node = window['app'].canvas.graph.getNodeById(id)
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const node = app.canvas.graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
if (!node.widgets) throw new Error(`Node ${id} has no widgets.`)
const widget = node.widgets[index]
if (!widget) throw new Error(`Widget ${index} not found.`)
const [x, y, w, h] = node.getBounding()
return window['app'].canvasPosToClientPos([
const [x, y, w] = node.getBounding()
const titleHeight = window.LiteGraph?.NODE_TITLE_HEIGHT ?? 20
return app.canvasPosToClientPos([
x + w / 2,
y + window['LiteGraph']['NODE_TITLE_HEIGHT'] + widget.last_y + 1
y + titleHeight + (widget.last_y ?? 0) + 1
])
},
[this.node.id, this.index] as const
@@ -239,8 +255,11 @@ class NodeWidgetReference {
async getSocketPosition(): Promise<Position> {
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
([id, index]) => {
const node = window['app'].graph.getNodeById(id)
const app = window.app
if (!app?.graph) throw new Error('App not initialized')
const node = app.graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
if (!node.widgets) throw new Error(`Node ${id} has no widgets.`)
const widget = node.widgets[index]
if (!widget) throw new Error(`Widget ${index} not found.`)
@@ -248,11 +267,13 @@ class NodeWidgetReference {
(slot) => slot.widget?.name === widget.name
)
if (!slot) throw new Error(`Socket ${widget.name} not found.`)
if (!slot.pos) throw new Error(`Socket ${widget.name} has no position.`)
const [x, y] = node.getBounding()
return window['app'].canvasPosToClientPos([
const titleHeight = window.LiteGraph?.NODE_TITLE_HEIGHT ?? 20
return app.canvasPosToClientPos([
x + slot.pos[0],
y + slot.pos[1] + window['LiteGraph']['NODE_TITLE_HEIGHT']
y + slot.pos[1] + titleHeight
])
},
[this.node.id, this.index] as const
@@ -288,8 +309,11 @@ class NodeWidgetReference {
async getValue() {
return await this.node.comfyPage.page.evaluate(
([id, index]) => {
const node = window['app'].graph.getNodeById(id)
const app = window.app
if (!app?.graph) throw new Error('App not initialized')
const node = app.graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
if (!node.widgets) throw new Error(`Node ${id} has no widgets.`)
const widget = node.widgets[index]
if (!widget) throw new Error(`Widget ${index} not found.`)
return widget.value
@@ -305,7 +329,9 @@ export class NodeReference {
) {}
async exists(): Promise<boolean> {
return await this.comfyPage.page.evaluate((id) => {
const node = window['app'].canvas.graph.getNodeById(id)
const app = window.app
if (!app?.canvas?.graph) return false
const node = app.canvas.graph.getNodeById(id)
return !!node
}, this.id)
}
@@ -322,17 +348,19 @@ export class NodeReference {
}
}
async getBounding(): Promise<Position & Size> {
const [x, y, width, height]: [number, number, number, number] =
await this.comfyPage.page.evaluate((id) => {
const node = window['app'].canvas.graph.getNodeById(id)
if (!node) throw new Error('Node not found')
return node.getBounding()
}, this.id)
const bounding = await this.comfyPage.page.evaluate((id) => {
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const node = app.canvas.graph.getNodeById(id)
if (!node) throw new Error('Node not found')
const b = node.getBounding()
return [b[0], b[1], b[2], b[3]] as [number, number, number, number]
}, this.id)
return {
x,
y,
width,
height
x: bounding[0],
y: bounding[1],
width: bounding[2],
height: bounding[3]
}
}
async getSize(): Promise<Size> {
@@ -355,14 +383,16 @@ export class NodeReference {
return (await this.getProperty<number | null | undefined>('mode')) === 4
}
async getProperty<T>(prop: string): Promise<T> {
return await this.comfyPage.page.evaluate(
return (await this.comfyPage.page.evaluate(
([id, prop]) => {
const node = window['app'].canvas.graph.getNodeById(id)
const app = window.app
if (!app?.canvas?.graph) throw new Error('App not initialized')
const node = app.canvas.graph.getNodeById(id)
if (!node) throw new Error('Node not found')
return node[prop]
return (node as unknown as Record<string, unknown>)[prop]
},
[this.id, prop] as const
)
)) as T
}
async getOutput(index: number) {
return new NodeSlotReference('output', index, this)
@@ -480,7 +510,7 @@ export class NodeReference {
}
async navigateIntoSubgraph() {
const titleHeight = await this.comfyPage.page.evaluate(() => {
return window['LiteGraph']['NODE_TITLE_HEIGHT']
return window.LiteGraph?.NODE_TITLE_HEIGHT ?? 20
})
const nodePos = await this.getPosition()
const nodeSize = await this.getSize()
@@ -513,7 +543,9 @@ export class NodeReference {
// Check if we successfully entered the subgraph
isInSubgraph = await this.comfyPage.page.evaluate(() => {
const graph = window['app'].canvas.graph
const app = window.app
if (!app) return false
const graph = app.canvas.graph
return graph?.constructor?.name === 'Subgraph'
})

View File

@@ -120,15 +120,23 @@ export default class TaskHistory {
filenames: string[],
filetype: OutputFileType
): TaskOutput {
return filenames.reduce((outputs, filename, i) => {
const nodeId = `${i + 1}`
outputs[nodeId] = {
[filetype]: [{ filename, subfolder: '', type: 'output' }]
}
const contentType = getContentType(filename, filetype)
this.outputContentTypes.set(filename, contentType)
return outputs
}, {})
return filenames.reduce(
(outputs, filename, i) => {
const nodeId = `${i + 1}`
outputs[nodeId] = {
[filetype]: [{ filename, subfolder: '', type: 'output' }]
}
const contentType = getContentType(filename, filetype)
this.outputContentTypes.set(filename, contentType)
return outputs
},
{} as Record<
string,
{
[key: string]: { filename: string; subfolder: string; type: string }[]
}
>
)
}
private addTask(task: HistoryTaskItem) {