diff --git a/src/extensions/core/groupNode.ts b/src/extensions/core/groupNode.ts index a7af7361a..db543c30a 100644 --- a/src/extensions/core/groupNode.ts +++ b/src/extensions/core/groupNode.ts @@ -368,7 +368,7 @@ export class GroupNodeConfig { } getNodeDef( - node: GroupNodeData + node: GroupNodeData | GroupNodeWorkflowData['nodes'][number] ): GroupNodeDef | ComfyNodeDef | null | undefined { if (node.type) { const def = globalDefs[node.type] @@ -386,7 +386,8 @@ export class GroupNodeConfig { let type: string | number | null = linksFrom[0]?.[0]?.[5] ?? null if (type === 'COMBO') { // Use the array items - const source = node.outputs?.[0]?.widget?.name + const output = node.outputs?.[0] as GroupNodeOutput | undefined + const source = output?.widget?.name const nodeIdx = linksFrom[0]?.[0]?.[2] if (source && nodeIdx != null) { const fromTypeName = this.nodeData.nodes[Number(nodeIdx)]?.type diff --git a/src/extensions/core/groupNodeManage.ts b/src/extensions/core/groupNodeManage.ts index 0e91af317..38bddb129 100644 --- a/src/extensions/core/groupNodeManage.ts +++ b/src/extensions/core/groupNodeManage.ts @@ -1,9 +1,11 @@ import { PREFIX, SEPARATOR } from '@/constants/groupNodeConstants' -import { - type LGraphNode, - type LGraphNodeConstructor, - LiteGraph +import type { + GroupNodeConfigEntry, + GroupNodeWorkflowData, + LGraphNode, + LGraphNodeConstructor } from '@/lib/litegraph/src/litegraph' +import { LiteGraph } from '@/lib/litegraph/src/litegraph' import { useToastStore } from '@/platform/updates/common/toastStore' import { type ComfyApp, app } from '../../scripts/app' @@ -15,18 +17,20 @@ import './groupNodeManage.css' const ORDER: symbol = Symbol() -// @ts-expect-error fixme ts strict error -function merge(target, source) { - if (typeof target === 'object' && typeof source === 'object') { - for (const key in source) { - const sv = source[key] - if (typeof sv === 'object') { - let tv = target[key] - if (!tv) tv = target[key] = {} - merge(tv, source[key]) - } else { - target[key] = sv +function merge( + target: Record, + source: Record +): Record { + for (const key in source) { + const sv = source[key] + if (typeof sv === 'object' && sv !== null) { + let tv = target[key] as Record | undefined + if (!tv) { + tv = target[key] = {} } + merge(tv, sv as Record) + } else { + target[key] = sv } } @@ -34,8 +38,7 @@ function merge(target, source) { } export class ManageGroupDialog extends ComfyDialog { - // @ts-expect-error fixme ts strict error - tabs: Record< + tabs!: Record< 'Inputs' | 'Outputs' | 'Widgets', { tab: HTMLAnchorElement; page: HTMLElement } > @@ -52,31 +55,26 @@ export class ManageGroupDialog extends ComfyDialog { > > > = {} - // @ts-expect-error fixme ts strict error - nodeItems: any[] + nodeItems!: HTMLLIElement[] app: ComfyApp - // @ts-expect-error fixme ts strict error - groupNodeType: LGraphNodeConstructor - groupNodeDef: any - groupData: any + groupNodeType!: LGraphNodeConstructor + groupData!: GroupNodeConfig - // @ts-expect-error fixme ts strict error - innerNodesList: HTMLUListElement - // @ts-expect-error fixme ts strict error - widgetsPage: HTMLElement - // @ts-expect-error fixme ts strict error - inputsPage: HTMLElement - // @ts-expect-error fixme ts strict error - outputsPage: HTMLElement - draggable: any + innerNodesList!: HTMLUListElement + widgetsPage!: HTMLElement + inputsPage!: HTMLElement + outputsPage!: HTMLElement + draggable: DraggableList | undefined - get selectedNodeInnerIndex() { - // @ts-expect-error fixme ts strict error - return +this.nodeItems[this.selectedNodeIndex].dataset.nodeindex + get selectedNodeInnerIndex(): number { + const index = this.selectedNodeIndex + if (index == null) throw new Error('No node selected') + const item = this.nodeItems[index] + if (!item?.dataset.nodeindex) throw new Error('Invalid node item') + return +item.dataset.nodeindex } - // @ts-expect-error fixme ts strict error - constructor(app) { + constructor(app: ComfyApp) { super() this.app = app this.element = $el('dialog.comfy-group-manage', { @@ -84,19 +82,15 @@ export class ManageGroupDialog extends ComfyDialog { }) as HTMLDialogElement } - // @ts-expect-error fixme ts strict error - changeTab(tab) { + changeTab(tab: keyof ManageGroupDialog['tabs']): void { this.tabs[this.selectedTab].tab.classList.remove('active') this.tabs[this.selectedTab].page.classList.remove('active') - // @ts-expect-error fixme ts strict error this.tabs[tab].tab.classList.add('active') - // @ts-expect-error fixme ts strict error this.tabs[tab].page.classList.add('active') this.selectedTab = tab } - // @ts-expect-error fixme ts strict error - changeNode(index, force?) { + changeNode(index: number, force?: boolean): void { if (!force && this.selectedNodeIndex === index) return if (this.selectedNodeIndex != null) { @@ -122,43 +116,41 @@ export class ManageGroupDialog extends ComfyDialog { this.groupNodeType = LiteGraph.registered_node_types[ `${PREFIX}${SEPARATOR}` + this.selectedGroup ] as unknown as LGraphNodeConstructor - this.groupNodeDef = this.groupNodeType.nodeData - this.groupData = GroupNodeHandler.getGroupData(this.groupNodeType) + this.groupData = GroupNodeHandler.getGroupData(this.groupNodeType)! } - // @ts-expect-error fixme ts strict error - changeGroup(group, reset = true) { + changeGroup(group: string, reset = true): void { this.selectedGroup = group this.getGroupData() const nodes = this.groupData.nodeData.nodes - // @ts-expect-error fixme ts strict error - this.nodeItems = nodes.map((n, i) => - $el( - 'li.draggable-item', - { - dataset: { - nodeindex: n.index + '' - }, - onclick: () => { - this.changeNode(i) - } - }, - [ - $el('span.drag-handle'), - $el( - 'div', - { - textContent: n.title ?? n.type + this.nodeItems = nodes.map( + (n, i) => + $el( + 'li.draggable-item', + { + dataset: { + nodeindex: n.index + '' }, - n.title - ? $el('span', { - textContent: n.type - }) - : [] - ) - ] - ) + onclick: () => { + this.changeNode(i) + } + }, + [ + $el('span.drag-handle'), + $el( + 'div', + { + textContent: n.title ?? n.type + }, + n.title + ? $el('span', { + textContent: n.type + }) + : [] + ) + ] + ) as HTMLLIElement ) this.innerNodesList.replaceChildren(...this.nodeItems) @@ -167,47 +159,46 @@ export class ManageGroupDialog extends ComfyDialog { this.selectedNodeIndex = null this.changeNode(0) } else { - const items = this.draggable.getAllItems() - // @ts-expect-error fixme ts strict error - let index = items.findIndex((item) => item.classList.contains('selected')) - if (index === -1) index = this.selectedNodeIndex + const items = this.draggable!.getAllItems() + let index = items.findIndex((item: Element) => + item.classList.contains('selected') + ) + if (index === -1) index = this.selectedNodeIndex! this.changeNode(index, true) } const ordered = [...nodes] this.draggable?.dispose() this.draggable = new DraggableList(this.innerNodesList, 'li') - this.draggable.addEventListener( - 'dragend', - // @ts-expect-error fixme ts strict error - ({ detail: { oldPosition, newPosition } }) => { - if (oldPosition === newPosition) return - ordered.splice(newPosition, 0, ordered.splice(oldPosition, 1)[0]) - for (let i = 0; i < ordered.length; i++) { - this.storeModification({ - nodeIndex: ordered[i].index, - section: ORDER, - prop: 'order', - value: i - }) - } + this.draggable.addEventListener('dragend', (e: Event) => { + const { oldPosition, newPosition } = (e as CustomEvent).detail + if (oldPosition === newPosition) return + ordered.splice(newPosition, 0, ordered.splice(oldPosition, 1)[0]) + for (let i = 0; i < ordered.length; i++) { + this.storeModification({ + nodeIndex: ordered[i].index, + section: ORDER, + prop: 'order', + value: i + }) } - ) + }) } storeModification(props: { nodeIndex?: number - section: symbol + section: string | symbol prop: string - value: any + value: unknown }) { const { nodeIndex, section, prop, value } = props - // @ts-expect-error fixme ts strict error - const groupMod = (this.modifications[this.selectedGroup] ??= {}) - const nodesMod = (groupMod.nodes ??= {}) + const groupKey = this.selectedGroup! + const groupMod = (this.modifications[groupKey] ??= {}) + const nodesMod = ((groupMod as Record).nodes ??= + {}) as Record>> const nodeMod = (nodesMod[nodeIndex ?? this.selectedNodeInnerIndex] ??= {}) const typeMod = (nodeMod[section] ??= {}) - if (typeof value === 'object') { + if (typeof value === 'object' && value !== null) { const objMod = (typeMod[prop] ??= {}) Object.assign(objMod, value) } else { @@ -215,35 +206,45 @@ export class ManageGroupDialog extends ComfyDialog { } } - // @ts-expect-error fixme ts strict error - getEditElement(section, prop, value, placeholder, checked, checkable = true) { - if (value === placeholder) value = '' + getEditElement( + section: string, + prop: string | number, + value: unknown, + placeholder: string, + checked: boolean, + checkable = true + ): HTMLDivElement { + let displayValue = value === placeholder ? '' : value - const mods = - // @ts-expect-error fixme ts strict error - this.modifications[this.selectedGroup]?.nodes?.[ - this.selectedNodeInnerIndex - ]?.[section]?.[prop] - if (mods) { - if (mods.name != null) { - value = mods.name + const groupKey = this.selectedGroup! + const mods = ( + this.modifications[groupKey] as Record | undefined + )?.nodes as + | Record< + number, + Record> + > + | undefined + const modEntry = mods?.[this.selectedNodeInnerIndex]?.[section]?.[prop] + if (modEntry) { + if (modEntry.name != null) { + displayValue = modEntry.name } - if (mods.visible != null) { - checked = mods.visible + if (modEntry.visible != null) { + checked = modEntry.visible } } return $el('div', [ $el('input', { - value, + value: displayValue as string, placeholder, type: 'text', - // @ts-expect-error fixme ts strict error - onchange: (e) => { + onchange: (e: Event) => { this.storeModification({ section, - prop, - value: { name: e.target.value } + prop: String(prop), + value: { name: (e.target as HTMLInputElement).value } }) } }), @@ -252,25 +253,23 @@ export class ManageGroupDialog extends ComfyDialog { type: 'checkbox', checked, disabled: !checkable, - // @ts-expect-error fixme ts strict error - onchange: (e) => { + onchange: (e: Event) => { this.storeModification({ section, - prop, - value: { visible: !!e.target.checked } + prop: String(prop), + value: { visible: !!(e.target as HTMLInputElement).checked } }) } }) ]) - ]) + ]) as HTMLDivElement } buildWidgetsPage() { const widgets = this.groupData.oldToNewWidgetMap[this.selectedNodeInnerIndex] const items = Object.keys(widgets ?? {}) - // @ts-expect-error fixme ts strict error - const type = app.rootGraph.extra.groupNodes[this.selectedGroup] + const type = app.rootGraph.extra.groupNodes![this.selectedGroup!]! const config = type.config?.[this.selectedNodeInnerIndex]?.input this.widgetsPage.replaceChildren( ...items.map((oldName) => { @@ -289,28 +288,25 @@ export class ManageGroupDialog extends ComfyDialog { buildInputsPage() { const inputs = this.groupData.nodeInputs[this.selectedNodeInnerIndex] const items = Object.keys(inputs ?? {}) - // @ts-expect-error fixme ts strict error - const type = app.rootGraph.extra.groupNodes[this.selectedGroup] + const type = app.rootGraph.extra.groupNodes![this.selectedGroup!]! const config = type.config?.[this.selectedNodeInnerIndex]?.input - this.inputsPage.replaceChildren( - // @ts-expect-error fixme ts strict error - ...items - .map((oldName) => { - let value = inputs[oldName] - if (!value) { - return - } + const elements = items + .map((oldName) => { + const value = inputs[oldName] + if (!value) { + return null + } - return this.getEditElement( - 'input', - oldName, - value, - oldName, - config?.[oldName]?.visible !== false - ) - }) - .filter(Boolean) - ) + return this.getEditElement( + 'input', + oldName, + value, + oldName, + config?.[oldName]?.visible !== false + ) + }) + .filter((el): el is HTMLDivElement => el !== null) + this.inputsPage.replaceChildren(...elements) return !!items.length } @@ -323,38 +319,35 @@ export class ManageGroupDialog extends ComfyDialog { const groupOutputs = this.groupData.oldToNewOutputMap[this.selectedNodeInnerIndex] - // @ts-expect-error fixme ts strict error - const type = app.rootGraph.extra.groupNodes[this.selectedGroup] + const type = app.rootGraph.extra.groupNodes![this.selectedGroup!]! const config = type.config?.[this.selectedNodeInnerIndex]?.output const node = this.groupData.nodeData.nodes[this.selectedNodeInnerIndex] const checkable = node.type !== 'PrimitiveNode' - this.outputsPage.replaceChildren( - ...outputs - // @ts-expect-error fixme ts strict error - .map((type, slot) => { - const groupOutputIndex = groupOutputs?.[slot] - const oldName = innerNodeDef.output_name?.[slot] ?? type - let value = config?.[slot]?.name - const visible = config?.[slot]?.visible || groupOutputIndex != null - if (!value || value === oldName) { - value = '' - } - return this.getEditElement( - 'output', - slot, - value, - oldName, - visible, - checkable - ) - }) - .filter(Boolean) - ) + const elements = outputs.map((outputType: unknown, slot: number) => { + const groupOutputIndex = groupOutputs?.[slot] + const oldName = innerNodeDef?.output_name?.[slot] ?? String(outputType) + let value = config?.[slot]?.name + const visible = config?.[slot]?.visible || groupOutputIndex != null + if (!value || value === oldName) { + value = '' + } + return this.getEditElement( + 'output', + slot, + value, + oldName, + visible, + checkable + ) + }) + this.outputsPage.replaceChildren(...elements) return !!outputs.length } - // @ts-expect-error fixme ts strict error - show(type?) { + override show(groupNodeType?: string | HTMLElement | HTMLElement[]): void { + // Extract string type - this method repurposes the show signature + const nodeType = + typeof groupNodeType === 'string' ? groupNodeType : undefined const groupNodes = Object.keys(app.rootGraph.extra?.groupNodes ?? {}).sort( (a, b) => a.localeCompare(b) ) @@ -371,24 +364,27 @@ export class ManageGroupDialog extends ComfyDialog { this.outputsPage ]) - this.tabs = [ + type TabName = 'Inputs' | 'Widgets' | 'Outputs' + const tabEntries: [TabName, HTMLElement][] = [ ['Inputs', this.inputsPage], ['Widgets', this.widgetsPage], ['Outputs', this.outputsPage] - // @ts-expect-error fixme ts strict error - ].reduce((p, [name, page]: [string, HTMLElement]) => { - // @ts-expect-error fixme ts strict error - p[name] = { - tab: $el('a', { - onclick: () => { - this.changeTab(name) - }, - textContent: name - }), - page - } - return p - }, {}) as any + ] + this.tabs = tabEntries.reduce( + (p, [name, page]) => { + p[name] = { + tab: $el('a', { + onclick: () => { + this.changeTab(name) + }, + textContent: name + }) as HTMLAnchorElement, + page + } + return p + }, + {} as ManageGroupDialog['tabs'] + ) const outer = $el('div.comfy-group-manage-outer', [ $el('header', [ @@ -396,15 +392,14 @@ export class ManageGroupDialog extends ComfyDialog { $el( 'select', { - // @ts-expect-error fixme ts strict error - onchange: (e) => { - this.changeGroup(e.target.value) + onchange: (e: Event) => { + this.changeGroup((e.target as HTMLSelectElement).value) } }, groupNodes.map((g) => $el('option', { textContent: g, - selected: `${PREFIX}${SEPARATOR}${g}` === type, + selected: `${PREFIX}${SEPARATOR}${g}` === nodeType, value: g }) ) @@ -439,8 +434,7 @@ export class ManageGroupDialog extends ComfyDialog { `Are you sure you want to remove the node: "${this.selectedGroup}"` ) ) { - // @ts-expect-error fixme ts strict error - delete app.rootGraph.extra.groupNodes[this.selectedGroup] + delete app.rootGraph.extra.groupNodes![this.selectedGroup!] LiteGraph.unregisterNodeType( `${PREFIX}${SEPARATOR}` + this.selectedGroup ) @@ -454,97 +448,106 @@ export class ManageGroupDialog extends ComfyDialog { 'button.comfy-btn', { onclick: async () => { - let nodesByType - let recreateNodes = [] - const types = {} + type NodesByType = Record + let nodesByType: NodesByType | undefined + const recreateNodes: LGraphNode[] = [] + const types: Record = {} for (const g in this.modifications) { - // @ts-expect-error fixme ts strict error - const type = app.rootGraph.extra.groupNodes[g] - let config = (type.config ??= {}) + const groupNodeData = app.rootGraph.extra.groupNodes![g]! + let config = (groupNodeData.config ??= {}) - let nodeMods = this.modifications[g]?.nodes + type NodeMods = Record< + string, + Record> + > + let nodeMods = this.modifications[g]?.nodes as + | NodeMods + | undefined if (nodeMods) { const keys = Object.keys(nodeMods) - // @ts-expect-error fixme ts strict error - if (nodeMods[keys[0]][ORDER]) { + if (nodeMods[keys[0]]?.[ORDER]) { // If any node is reordered, they will all need sequencing - const orderedNodes = [] - const orderedMods = {} - const orderedConfig = {} + const orderedNodes: GroupNodeWorkflowData['nodes'] = [] + const orderedMods: NodeMods = {} + const orderedConfig: Record = + {} for (const n of keys) { - // @ts-expect-error fixme ts strict error - const order = nodeMods[n][ORDER].order - orderedNodes[order] = type.nodes[+n] - // @ts-expect-error fixme ts strict error + const order = (nodeMods[n][ORDER] as { order: number }) + .order + orderedNodes[order] = groupNodeData.nodes[+n] orderedMods[order] = nodeMods[n] orderedNodes[order].index = order } // Rewrite links - for (const l of type.links) { - // @ts-expect-error l[0]/l[2] used as node index - if (l[0] != null) l[0] = type.nodes[l[0]].index - // @ts-expect-error l[0]/l[2] used as node index - if (l[2] != null) l[2] = type.nodes[l[2]].index + const nodesLen = groupNodeData.nodes.length + for (const l of groupNodeData.links) { + const srcIdx = l[0] as number + const dstIdx = l[2] as number + if (srcIdx != null && srcIdx < nodesLen) + l[0] = groupNodeData.nodes[srcIdx].index! + if (dstIdx != null && dstIdx < nodesLen) + l[2] = groupNodeData.nodes[dstIdx].index! } // Rewrite externals - if (type.external) { - for (const ext of type.external) { - if (ext[0] != null) { - // @ts-expect-error ext[0] used as node index - ext[0] = type.nodes[ext[0]].index + if (groupNodeData.external) { + for (const ext of groupNodeData.external) { + const extIdx = ext[0] as number + if (extIdx != null && extIdx < nodesLen) { + ext[0] = groupNodeData.nodes[extIdx].index! } } } // Rewrite modifications for (const id of keys) { - // @ts-expect-error id used as node index - if (config[id]) { - // @ts-expect-error fixme ts strict error - orderedConfig[type.nodes[id].index] = config[id] + if (config[+id]) { + orderedConfig[groupNodeData.nodes[+id].index!] = + config[+id] } - // @ts-expect-error id used as config key - delete config[id] + delete config[+id] } - type.nodes = orderedNodes + groupNodeData.nodes = orderedNodes nodeMods = orderedMods - type.config = config = orderedConfig + groupNodeData.config = config = orderedConfig } - merge(config, nodeMods) + merge( + config as Record, + nodeMods as Record + ) } - // @ts-expect-error fixme ts strict error - types[g] = type + types[g] = groupNodeData if (!nodesByType) { - nodesByType = app.rootGraph.nodes.reduce((p, n) => { - // @ts-expect-error fixme ts strict error - p[n.type] ??= [] - // @ts-expect-error fixme ts strict error - p[n.type].push(n) - return p - }, {}) + nodesByType = app.rootGraph.nodes.reduce( + (p, n) => { + const nodeType = n.type ?? '' + p[nodeType] ??= [] + p[nodeType].push(n) + return p + }, + {} + ) } - // @ts-expect-error fixme ts strict error - const nodes = nodesByType[`${PREFIX}${SEPARATOR}` + g] - if (nodes) recreateNodes.push(...nodes) + const groupTypeNodes = nodesByType[`${PREFIX}${SEPARATOR}` + g] + if (groupTypeNodes) recreateNodes.push(...groupTypeNodes) } await GroupNodeConfig.registerFromWorkflow(types, []) for (const node of recreateNodes) { - node.recreate() + node.recreate?.() } this.modifications = {} this.app.canvas.setDirty(true, true) - this.changeGroup(this.selectedGroup, false) + this.changeGroup(this.selectedGroup!, false) } }, 'Save' @@ -559,8 +562,8 @@ export class ManageGroupDialog extends ComfyDialog { this.element.replaceChildren(outer) this.changeGroup( - type - ? (groupNodes.find((g) => `${PREFIX}${SEPARATOR}${g}` === type) ?? + nodeType + ? (groupNodes.find((g) => `${PREFIX}${SEPARATOR}${g}` === nodeType) ?? groupNodes[0]) : groupNodes[0] ) diff --git a/src/lib/litegraph/src/LGraph.ts b/src/lib/litegraph/src/LGraph.ts index 401de111b..49ad35101 100644 --- a/src/lib/litegraph/src/LGraph.ts +++ b/src/lib/litegraph/src/LGraph.ts @@ -102,16 +102,23 @@ export interface LGraphConfig { links_ontop?: boolean } +export interface GroupNodeConfigEntry { + input?: Record + output?: Record +} + export interface GroupNodeWorkflowData { external: (number | string)[][] links: SerialisedLLinkArray[] nodes: { index?: number type?: string + title?: string inputs?: unknown[] outputs?: unknown[] + widgets_values?: unknown[] }[] - config?: Record + config?: Record } export interface LGraphExtra extends Dictionary { diff --git a/src/lib/litegraph/src/litegraph.ts b/src/lib/litegraph/src/litegraph.ts index 0b24eb47b..59d62a84f 100644 --- a/src/lib/litegraph/src/litegraph.ts +++ b/src/lib/litegraph/src/litegraph.ts @@ -104,6 +104,8 @@ export type { } from './interfaces' export { LGraph, + type GroupNodeConfigEntry, + type GroupNodeWorkflowData, type LGraphTriggerAction, type LGraphTriggerParam } from './LGraph' diff --git a/src/schemas/apiSchema.ts b/src/schemas/apiSchema.ts index 64b0b5208..37833cf2f 100644 --- a/src/schemas/apiSchema.ts +++ b/src/schemas/apiSchema.ts @@ -13,6 +13,9 @@ export type PromptId = z.infer export const resultItemType = z.enum(['input', 'output', 'temp']) export type ResultItemType = z.infer +const zCustomNodesI18n = z.record(z.string(), z.unknown()) +export type CustomNodesI18n = z.infer + const zResultItem = z.object({ filename: z.string().optional(), subfolder: z.string().optional(), diff --git a/src/scripts/api.ts b/src/scripts/api.ts index 67f98826e..41310b0bd 100644 --- a/src/scripts/api.ts +++ b/src/scripts/api.ts @@ -22,6 +22,7 @@ import type { } from '@/platform/workflow/validation/schemas/workflowSchema' import type { AssetDownloadWsMessage, + CustomNodesI18n, EmbeddingsResponse, ExecutedWsMessage, ExecutingWsMessage, @@ -35,6 +36,7 @@ import type { LogsRawResponse, LogsWsMessage, NotificationWsMessage, + PreviewMethod, ProgressStateWsMessage, ProgressTextWsMessage, ProgressWsMessage, @@ -44,8 +46,7 @@ import type { StatusWsMessageStatus, SystemStats, User, - UserDataFullInfo, - PreviewMethod + UserDataFullInfo } from '@/schemas/apiSchema' import type { JobDetail, @@ -951,7 +952,7 @@ export class ComfyApi extends EventTarget { * @param {*} type The endpoint to post to * @param {*} body Optional POST data */ - async #postItem(type: string, body: any) { + async #postItem(type: string, body?: Record) { try { await this.fetchApi('/' + type, { method: 'POST', @@ -1074,7 +1075,7 @@ export class ComfyApi extends EventTarget { */ async storeUserData( file: string, - data: any, + data: unknown, options: RequestInit & { overwrite?: boolean stringify?: boolean @@ -1091,7 +1092,7 @@ export class ComfyApi extends EventTarget { `/userdata/${encodeURIComponent(file)}?overwrite=${options.overwrite}&full_info=${options.full_info}`, { method: 'POST', - body: options?.stringify ? JSON.stringify(data) : data, + body: options?.stringify ? JSON.stringify(data) : (data as BodyInit), ...options } ) @@ -1251,7 +1252,7 @@ export class ComfyApi extends EventTarget { * * @returns The custom nodes i18n data */ - async getCustomNodesI18n(): Promise> { + async getCustomNodesI18n(): Promise { return (await axios.get(this.apiURL('/i18n'))).data } diff --git a/src/scripts/changeTracker.ts b/src/scripts/changeTracker.ts index fa09ad49a..4db14677a 100644 --- a/src/scripts/changeTracker.ts +++ b/src/scripts/changeTracker.ts @@ -2,6 +2,7 @@ import _ from 'es-toolkit/compat' import * as jsondiffpatch from 'jsondiffpatch' import log from 'loglevel' +import type { CanvasPointerEvent } from '@/lib/litegraph/src/litegraph' import { LGraphCanvas, LiteGraph } from '@/lib/litegraph/src/litegraph' import { ComfyWorkflow, @@ -40,7 +41,7 @@ export class ChangeTracker { _restoringState: boolean = false ds?: { scale: number; offset: [number, number] } - nodeOutputs?: Record + nodeOutputs?: Record private subgraphState?: { navigation: string[] @@ -303,11 +304,11 @@ export class ChangeTracker { const prompt = LGraphCanvas.prototype.prompt LGraphCanvas.prototype.prompt = function ( title: string, - value: any, - callback: (v: any) => void, - event: any + value: string | number, + callback: (v: string) => void, + event: CanvasPointerEvent ) { - const extendedCallback = (v: any) => { + const extendedCallback = (v: string) => { callback(v) checkState() } diff --git a/src/scripts/ui/components/asyncDialog.ts b/src/scripts/ui/components/asyncDialog.ts index 1da1a5a4e..d1f45a9de 100644 --- a/src/scripts/ui/components/asyncDialog.ts +++ b/src/scripts/ui/components/asyncDialog.ts @@ -1,28 +1,28 @@ import { $el } from '../../ui' import { ComfyDialog } from '../dialog' -export class ComfyAsyncDialog extends ComfyDialog { - // @ts-expect-error fixme ts strict error - #resolve: (value: any) => void +type DialogAction = string | { value?: T; text: string } - constructor(actions?: Array) { +export class ComfyAsyncDialog< + T = string | null +> extends ComfyDialog { + #resolve: (value: T | null) => void = () => {} + + constructor(actions?: Array>) { super( 'dialog.comfy-dialog.comfyui-dialog', - // @ts-expect-error fixme ts strict error actions?.map((opt) => { - if (typeof opt === 'string') { - opt = { text: opt } - } + const action = typeof opt === 'string' ? { text: opt } : opt return $el('button.comfyui-button', { type: 'button', - textContent: opt.text, - onclick: () => this.close(opt.value ?? opt.text) - }) + textContent: action.text, + onclick: () => this.close((action.value ?? action.text) as T) + }) as HTMLButtonElement }) ) } - override show(html: string | HTMLElement | HTMLElement[]) { + override show(html: string | HTMLElement | HTMLElement[]): Promise { this.element.addEventListener('close', () => { this.close() }) @@ -34,7 +34,7 @@ export class ComfyAsyncDialog extends ComfyDialog { }) } - showModal(html: string | HTMLElement | HTMLElement[]) { + showModal(html: string | HTMLElement | HTMLElement[]): Promise { this.element.addEventListener('close', () => { this.close() }) @@ -47,22 +47,22 @@ export class ComfyAsyncDialog extends ComfyDialog { }) } - override close(result = null) { + override close(result: T | null = null) { this.#resolve(result) this.element.close() super.close() } - static async prompt({ + static async prompt({ title = null, message, actions }: { title: string | null message: string - actions: Array - }) { - const dialog = new ComfyAsyncDialog(actions) + actions: Array> + }): Promise { + const dialog = new ComfyAsyncDialog(actions) const content = [$el('span', message)] if (title) { content.unshift($el('h3', title)) diff --git a/src/scripts/ui/dialog.ts b/src/scripts/ui/dialog.ts index 23d43c2bd..12ca4a2e5 100644 --- a/src/scripts/ui/dialog.ts +++ b/src/scripts/ui/dialog.ts @@ -4,11 +4,10 @@ export class ComfyDialog< T extends HTMLElement = HTMLElement > extends EventTarget { element: T - // @ts-expect-error fixme ts strict error - textElement: HTMLElement + textElement!: HTMLElement #buttons: HTMLButtonElement[] | null - constructor(type = 'div', buttons = null) { + constructor(type = 'div', buttons: HTMLButtonElement[] | null = null) { super() this.#buttons = buttons this.element = $el(type + '.comfy-modal', { parent: document.body }, [ @@ -35,8 +34,7 @@ export class ComfyDialog< this.element.style.display = 'none' } - // @ts-expect-error fixme ts strict error - show(html) { + show(html: string | HTMLElement | HTMLElement[]): void { if (typeof html === 'string') { this.textElement.innerHTML = html } else {