[TS] Enable strict mode (#3136)

This commit is contained in:
Chenlei Hu
2025-03-18 22:57:17 -04:00
committed by GitHub
parent 44edec7ad2
commit a049e9ae2d
64 changed files with 924 additions and 781 deletions

View File

@@ -1,4 +1,3 @@
// @ts-strict-ignore
import {
LGraph,
LGraphCanvas,
@@ -62,6 +61,7 @@ import { type ComfyWidgetConstructor, ComfyWidgets } from './widgets'
export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview'
// @ts-expect-error fixme ts strict error
function sanitizeNodeName(string) {
let entityMap = {
'&': '',
@@ -73,6 +73,7 @@ function sanitizeNodeName(string) {
'=': ''
}
return String(string).replace(/[&<>"'`=]/g, function fromEntityMap(s) {
// @ts-expect-error fixme ts strict error
return entityMap[s]
})
}
@@ -110,17 +111,27 @@ export class ComfyApp {
vueAppReady: boolean
api: ComfyApi
ui: ComfyUI
// @ts-expect-error fixme ts strict error
extensionManager: ExtensionManager
// @ts-expect-error fixme ts strict error
_nodeOutputs: Record<string, any>
nodePreviewImages: Record<string, string[]>
// @ts-expect-error fixme ts strict error
graph: LGraph
// @ts-expect-error fixme ts strict error
canvas: LGraphCanvas
// @ts-expect-error fixme ts strict error
dragOverNode: LGraphNode | null
// @ts-expect-error fixme ts strict error
canvasEl: HTMLCanvasElement
// @ts-expect-error fixme ts strict error
lastNodeErrors: any[] | null
/** @type {ExecutionErrorWsMessage} */
// @ts-expect-error fixme ts strict error
lastExecutionError: { node_id?: NodeId } | null
// @ts-expect-error fixme ts strict error
configuringGraph: boolean
// @ts-expect-error fixme ts strict error
ctx: CanvasRenderingContext2D
bodyTop: HTMLElement
bodyLeft: HTMLElement
@@ -258,9 +269,11 @@ export class ComfyApp {
ComfyApp.clipspace_return_node = null
}
// @ts-expect-error fixme ts strict error
static copyToClipspace(node) {
var widgets = null
if (node.widgets) {
// @ts-expect-error fixme ts strict error
widgets = node.widgets.map(({ type, name, value }) => ({
type,
name,
@@ -361,6 +374,7 @@ export class ComfyApp {
}
if (ComfyApp.clipspace.widgets) {
ComfyApp.clipspace.widgets.forEach(({ type, name, value }) => {
// @ts-expect-error fixme ts strict error
const prop = Object.values(node.widgets).find(
(obj) => obj.type === type && obj.name === name
)
@@ -378,6 +392,7 @@ export class ComfyApp {
resultItem.filename +
(resultItem.type ? ` [${resultItem.type}]` : '')
} else {
// @ts-expect-error fixme ts strict error
prop.value = value
prop.callback?.(value)
}
@@ -394,6 +409,7 @@ export class ComfyApp {
const serialize = LGraph.prototype.serialize
const self = this
LGraph.prototype.serialize = function () {
// @ts-expect-error fixme ts strict error
const workflow = serialize.apply(this, arguments)
// Store the drag & scale info in the serialized workflow if the setting is enabled
@@ -432,17 +448,22 @@ export class ComfyApp {
}
// Dragging from Chrome->Firefox there is a file but its a bmp, so ignore that
if (
// @ts-expect-error fixme ts strict error
event.dataTransfer.files.length &&
// @ts-expect-error fixme ts strict error
event.dataTransfer.files[0].type !== 'image/bmp'
) {
// @ts-expect-error fixme ts strict error
await this.handleFile(event.dataTransfer.files[0])
} else {
// Try loading the first URI in the transfer list
const validTypes = ['text/uri-list', 'text/x-moz-url']
// @ts-expect-error fixme ts strict error
const match = [...event.dataTransfer.types].find((t) =>
validTypes.find((v) => t === v)
)
if (match) {
// @ts-expect-error fixme ts strict error
const uri = event.dataTransfer.getData(match)?.split('\n')?.[0]
if (uri) {
await this.handleFile(await (await fetch(uri)).blob())
@@ -533,6 +554,7 @@ export class ComfyApp {
}
// Fall through to Litegraph defaults
// @ts-expect-error fixme ts strict error
return origProcessKey.apply(this, arguments)
}
}
@@ -550,12 +572,15 @@ export class ComfyApp {
_fgcolor,
bgcolor
) {
// @ts-expect-error fixme ts strict error
const res = origDrawNodeShape.apply(this, arguments)
// @ts-expect-error fixme ts strict error
const nodeErrors = self.lastNodeErrors?.[node.id]
let color = null
let lineWidth = 1
// @ts-expect-error fixme ts strict error
if (node.id === +self.runningNodeId) {
color = '#0f0'
} else if (self.dragOverNode && node.id === self.dragOverNode.id) {
@@ -565,6 +590,7 @@ export class ComfyApp {
lineWidth = 2
} else if (
self.lastExecutionError &&
// @ts-expect-error fixme ts strict error
+self.lastExecutionError.node_id === node.id
) {
color = '#f0f'
@@ -587,6 +613,7 @@ export class ComfyApp {
})
}
// @ts-expect-error fixme ts strict error
if (self.progress && node.id === +self.runningNodeId) {
ctx.fillStyle = 'green'
ctx.fillRect(
@@ -659,6 +686,7 @@ export class ComfyApp {
node.bgcolor = adjustColor(bgColor, adjustments)
// @ts-expect-error fixme ts strict error
const res = origDrawNode.apply(this, arguments)
this.editor_alpha = editor_alpha
@@ -683,7 +711,9 @@ export class ComfyApp {
api.addEventListener('executing', () => {
this.graph.setDirtyCanvas(true, false)
// @ts-expect-error fixme ts strict error
this.revokePreviews(this.runningNodeId)
// @ts-expect-error fixme ts strict error
delete this.nodePreviewImages[this.runningNodeId]
})
@@ -741,6 +771,7 @@ export class ComfyApp {
LGraph.prototype.configure = function () {
app.configuringGraph = true
try {
// @ts-expect-error fixme ts strict error
return configure.apply(this, arguments)
} finally {
app.configuringGraph = false
@@ -757,6 +788,7 @@ export class ComfyApp {
node.onGraphConfigured?.()
}
// @ts-expect-error fixme ts strict error
const r = onConfigure?.apply(this, arguments)
// Fire after onConfigure, used by primitives to generate widget using input nodes config
@@ -772,10 +804,15 @@ export class ComfyApp {
* Set up the app on the page
*/
async setup(canvasEl: HTMLCanvasElement) {
// @ts-expect-error fixme ts strict error
this.bodyTop = document.getElementById('comfyui-body-top')
// @ts-expect-error fixme ts strict error
this.bodyLeft = document.getElementById('comfyui-body-left')
// @ts-expect-error fixme ts strict error
this.bodyRight = document.getElementById('comfyui-body-right')
// @ts-expect-error fixme ts strict error
this.bodyBottom = document.getElementById('comfyui-body-bottom')
// @ts-expect-error fixme ts strict error
this.canvasContainer = document.getElementById('graph-canvas-container')
this.canvasEl = canvasEl
@@ -798,6 +835,7 @@ export class ComfyApp {
this.canvas.state = reactive(this.canvas.state)
this.canvas.ds.state = reactive(this.canvas.ds.state)
// @ts-expect-error fixme ts strict error
this.ctx = canvasEl.getContext('2d')
LiteGraph.alt_drag_do_clone_nodes = true
@@ -831,6 +869,7 @@ export class ComfyApp {
const { width, height } = this.canvasEl.getBoundingClientRect()
this.canvasEl.width = Math.round(width * scale)
this.canvasEl.height = Math.round(height * scale)
// @ts-expect-error fixme ts strict error
this.canvasEl.getContext('2d').scale(scale, scale)
this.canvas?.draw(true, true)
}
@@ -840,6 +879,7 @@ export class ComfyApp {
) {
// Frontend only nodes registered by custom nodes.
// Example: https://github.com/rgthree/rgthree-comfy/blob/dd534e5384be8cf0c0fa35865afe2126ba75ac55/src_web/comfyui/fast_groups_bypasser.ts#L10
// @ts-expect-error fixme ts strict error
const rawDefs: Record<string, ComfyNodeDefV1> = Object.fromEntries(
Object.entries(LiteGraph.registered_node_types).map(([name, node]) => [
name,
@@ -880,6 +920,7 @@ export class ComfyApp {
`nodeDefs.${def.name}.display_name`,
def.display_name ?? def.name
),
// @ts-expect-error fixme ts strict error
description: def.description
? st(`nodeDefs.${def.name}.description`, def.description)
: undefined,
@@ -906,6 +947,7 @@ export class ComfyApp {
await this.registerNodesFromDefs(defs)
await useExtensionService().invokeExtensionsAsync('registerCustomNodes')
if (this.vueAppReady) {
// @ts-expect-error fixme ts strict error
this.updateVueAppNodeDefs(defs)
}
}
@@ -923,6 +965,7 @@ export class ComfyApp {
}
}
// @ts-expect-error fixme ts strict error
loadTemplateData(templateData) {
if (!templateData?.templates) {
return
@@ -955,14 +998,17 @@ export class ComfyApp {
nodeBottom = node.pos[1] + node.size[1]
// @ts-expect-error fixme ts strict error
if (maxY === false || nodeBottom > maxY) {
maxY = nodeBottom
}
}
// @ts-expect-error fixme ts strict error
app.canvas.graph_mouse[1] = maxY + 50
}
// @ts-expect-error fixme ts strict error
localStorage.setItem('litegrapheditor_clipboard', old)
}
@@ -972,6 +1018,7 @@ export class ComfyApp {
}
}
// @ts-expect-error fixme ts strict error
#showMissingModelsError(missingModels, paths) {
if (useSettingStore().get('Comfy.Workflow.ShowMissingModelsWarning')) {
useDialogService().showMissingModelsWarning({
@@ -1092,7 +1139,9 @@ export class ComfyApp {
let errorHint = []
// Try extracting filename to see if it was caused by an extension script
const filename =
// @ts-expect-error fixme ts strict error
error.fileName ||
// @ts-expect-error fixme ts strict error
(error.stack || '').match(/(\/extensions\/.*\.js)/)?.[1]
const pos = (filename || '').indexOf('/extensions/')
if (pos > -1) {
@@ -1118,6 +1167,7 @@ export class ComfyApp {
}),
$el('pre', {
style: { padding: '5px', backgroundColor: 'rgba(255,0,0,0.2)' },
// @ts-expect-error fixme ts strict error
textContent: error.toString()
}),
$el('pre', {
@@ -1129,6 +1179,7 @@ export class ComfyApp {
overflow: 'auto',
backgroundColor: 'rgba(0,0,0,0.2)'
},
// @ts-expect-error fixme ts strict error
textContent: error.stack || 'No stacktrace available'
}),
...errorHint
@@ -1174,9 +1225,12 @@ export class ComfyApp {
if (reset_invalid_values) {
if (widget.type == 'combo') {
if (
// @ts-expect-error fixme ts strict error
!widget.options.values.includes(widget.value as string) &&
// @ts-expect-error fixme ts strict error
widget.options.values.length > 0
) {
// @ts-expect-error fixme ts strict error
widget.value = widget.options.values[0]
}
}
@@ -1225,6 +1279,7 @@ export class ComfyApp {
})
}
// @ts-expect-error fixme ts strict error
#formatPromptError(error) {
if (error == null) {
return '(unknown error)'
@@ -1251,10 +1306,12 @@ export class ComfyApp {
}
async queuePrompt(number: number, batchCount: number = 1): Promise<boolean> {
// @ts-expect-error fixme ts strict error
this.#queueItems.push({ number, batchCount })
// Only have one action process the items so each one gets a unique seed correctly
if (this.#processingQueue) {
// @ts-expect-error fixme ts strict error
return
}
@@ -1263,6 +1320,7 @@ export class ComfyApp {
try {
while (this.#queueItems.length) {
// @ts-expect-error fixme ts strict error
;({ number, batchCount } = this.#queueItems.pop())
for (let i = 0; i < batchCount; i++) {
@@ -1273,12 +1331,15 @@ export class ComfyApp {
const p = await this.graphToPrompt()
try {
const res = await api.queuePrompt(number, p)
// @ts-expect-error fixme ts strict error
this.lastNodeErrors = res.node_errors
// @ts-expect-error fixme ts strict error
if (this.lastNodeErrors.length > 0) {
this.canvas.draw(true, true)
} else {
try {
useExecutionStore().storePrompt({
// @ts-expect-error fixme ts strict error
id: res.prompt_id,
nodes: Object.keys(p.output),
workflow: useWorkspaceStore().workflow
@@ -1289,7 +1350,9 @@ export class ComfyApp {
} catch (error) {
const formattedError = this.#formatPromptError(error)
this.ui.dialog.show(formattedError)
// @ts-expect-error fixme ts strict error
if (error.response) {
// @ts-expect-error fixme ts strict error
this.lastNodeErrors = error.response.node_errors
this.canvas.draw(true, true)
}
@@ -1299,6 +1362,7 @@ export class ComfyApp {
// Allow widgets to run callbacks after a prompt has been queued
// e.g. random seed after every gen
executeWidgetsCallback(
// @ts-expect-error fixme ts strict error
p.workflow.nodes.map((n) => this.graph.getNodeById(n.id)),
'afterQueued'
)
@@ -1313,6 +1377,7 @@ export class ComfyApp {
return !this.lastNodeErrors
}
// @ts-expect-error fixme ts strict error
showErrorOnFileLoad(file) {
this.ui.dialog.show(
$el('div', [
@@ -1325,7 +1390,9 @@ export class ComfyApp {
* Loads workflow data from the specified file
* @param {File} file
*/
// @ts-expect-error fixme ts strict error
async handleFile(file) {
// @ts-expect-error fixme ts strict error
const removeExt = (f) => {
if (!f) return f
const p = f.lastIndexOf('.')
@@ -1437,11 +1504,13 @@ export class ComfyApp {
}
}
// @ts-expect-error fixme ts strict error
isApiJson(data) {
// @ts-expect-error
return Object.values(data).every((v) => v.class_type)
}
// @ts-expect-error fixme ts strict error
loadApiJson(apiData, fileName: string) {
useWorkflowService().beforeLoadNewGraph()
@@ -1462,8 +1531,11 @@ export class ComfyApp {
for (const id of ids) {
const data = apiData[id]
const node = LiteGraph.createNode(data.class_type)
// @ts-expect-error fixme ts strict error
node.id = isNaN(+id) ? id : +id
// @ts-expect-error fixme ts strict error
node.title = data._meta?.title ?? node.title
// @ts-expect-error fixme ts strict error
app.graph.add(node)
}
@@ -1475,21 +1547,26 @@ export class ComfyApp {
if (value instanceof Array) {
const [fromId, fromSlot] = value
const fromNode = app.graph.getNodeById(fromId)
// @ts-expect-error fixme ts strict error
let toSlot = node.inputs?.findIndex((inp) => inp.name === input)
if (toSlot == null || toSlot === -1) {
try {
// Target has no matching input, most likely a converted widget
// @ts-expect-error fixme ts strict error
const widget = node.widgets?.find((w) => w.name === input)
// @ts-expect-error
if (widget && node.convertWidgetToInput?.(widget)) {
// @ts-expect-error fixme ts strict error
toSlot = node.inputs?.length - 1
}
} catch (error) {}
}
if (toSlot != null || toSlot !== -1) {
// @ts-expect-error fixme ts strict error
fromNode.connect(fromSlot, node, toSlot)
}
} else {
// @ts-expect-error fixme ts strict error
const widget = node.widgets?.find((w) => w.name === input)
if (widget) {
widget.value = value
@@ -1508,21 +1585,26 @@ export class ComfyApp {
if (value instanceof Array) {
const [fromId, fromSlot] = value
const fromNode = app.graph.getNodeById(fromId)
// @ts-expect-error fixme ts strict error
let toSlot = node.inputs?.findIndex((inp) => inp.name === input)
if (toSlot == null || toSlot === -1) {
try {
// Target has no matching input, most likely a converted widget
// @ts-expect-error fixme ts strict error
const widget = node.widgets?.find((w) => w.name === input)
// @ts-expect-error
if (widget && node.convertWidgetToInput?.(widget)) {
// @ts-expect-error fixme ts strict error
toSlot = node.inputs?.length - 1
}
} catch (error) {}
}
if (toSlot != null || toSlot !== -1) {
// @ts-expect-error fixme ts strict error
fromNode.connect(fromSlot, node, toSlot)
}
} else {
// @ts-expect-error fixme ts strict error
const widget = node.widgets?.find((w) => w.name === input)
if (widget) {
widget.value = value
@@ -1565,19 +1647,19 @@ export class ComfyApp {
this.registerNodeDef(nodeId, defs[nodeId])
}
for (const node of this.graph.nodes) {
// @ts-expect-error fixme ts strict error
const def = defs[node.type]
// Allow primitive nodes to handle refresh
node.refreshComboInNode?.(defs)
if (!def?.input) continue
// @ts-expect-error fixme ts strict error
for (const widget of node.widgets) {
if (widget.type === 'combo') {
if (def['input'].required?.[widget.name] !== undefined) {
// @ts-expect-error InputSpec is not typed correctly
widget.options.values = def['input'].required[widget.name][0]
} else if (def['input'].optional?.[widget.name] !== undefined) {
// @ts-expect-error InputSpec is not typed correctly
widget.options.values = def['input'].optional[widget.name][0]
}
}
@@ -1590,6 +1672,7 @@ export class ComfyApp {
)
if (this.vueAppReady) {
// @ts-expect-error fixme ts strict error
this.updateVueAppNodeDefs(defs)
useToastStore().remove(requestToastMessage)
useToastStore().add({
@@ -1628,6 +1711,7 @@ export class ComfyApp {
const rect = this.canvasContainer.getBoundingClientRect()
const containerOffsets = [rect.left, rect.top]
return _.zip(pos, this.canvas.ds.offset, containerOffsets).map(
// @ts-expect-error fixme ts strict error
([p, o1, o2]) => (p - o2) / this.canvas.ds.scale - o1
) as Vector2
}
@@ -1636,6 +1720,7 @@ export class ComfyApp {
const rect = this.canvasContainer.getBoundingClientRect()
const containerOffsets = [rect.left, rect.top]
return _.zip(pos, this.canvas.ds.offset, containerOffsets).map(
// @ts-expect-error fixme ts strict error
([p, o1, o2]) => (p + o1) * this.canvas.ds.scale + o2
) as Vector2
}