diff --git a/src/composables/maskeditor/useToolManager.ts b/src/composables/maskeditor/useToolManager.ts index f51ce7b15..9b1847699 100644 --- a/src/composables/maskeditor/useToolManager.ts +++ b/src/composables/maskeditor/useToolManager.ts @@ -22,10 +22,10 @@ export function useToolManager( const coordinateTransform = useCoordinateTransform() const brushDrawing = useBrushDrawing({ - useDominantAxis: app.extensionManager.setting.get( + useDominantAxis: app.extensionManager.setting.get( 'Comfy.MaskEditor.UseDominantAxis' ), - brushAdjustmentSpeed: app.extensionManager.setting.get( + brushAdjustmentSpeed: app.extensionManager.setting.get( 'Comfy.MaskEditor.BrushAdjustmentSpeed' ) }) diff --git a/src/extensions/core/previewAny.ts b/src/extensions/core/previewAny.ts index fd8dd96f7..89fcf3cd8 100644 --- a/src/extensions/core/previewAny.ts +++ b/src/extensions/core/previewAny.ts @@ -74,7 +74,8 @@ useExtensionService().registerExtension({ this.widgets?.filter((w) => w.name === 'preview') ?? [] for (const previewWidget of previewWidgets) { - previewWidget.value = message.text[0] + const text = message.text ?? '' + previewWidget.value = Array.isArray(text) ? (text[0] ?? '') : text } } } diff --git a/src/platform/settings/constants/coreSettings.ts b/src/platform/settings/constants/coreSettings.ts index 5bc48e0bf..340a7c77c 100644 --- a/src/platform/settings/constants/coreSettings.ts +++ b/src/platform/settings/constants/coreSettings.ts @@ -602,10 +602,12 @@ export const CORE_SETTINGS: SettingParams[] = [ defaultValue: [] as Keybinding[], versionAdded: '1.3.7', versionModified: '1.7.3', - migrateDeprecatedValue: (value: any[]) => { + migrateDeprecatedValue: ( + value: (Keybinding & { targetSelector?: string })[] + ) => { return value.map((keybinding) => { - if (keybinding['targetSelector'] === '#graph-canvas') { - keybinding['targetElementId'] = 'graph-canvas-container' + if (keybinding.targetSelector === '#graph-canvas') { + keybinding.targetElementId = 'graph-canvas-container' } return keybinding }) @@ -780,7 +782,7 @@ export const CORE_SETTINGS: SettingParams[] = [ tooltip: 'Server config values used for frontend display only', type: 'hidden', // Mapping from server config id to value. - defaultValue: {} as Record, + defaultValue: {} as Record, versionAdded: '1.4.8' }, { diff --git a/src/platform/settings/settingStore.ts b/src/platform/settings/settingStore.ts index 83742de70..2c9e8e0a3 100644 --- a/src/platform/settings/settingStore.ts +++ b/src/platform/settings/settingStore.ts @@ -117,9 +117,10 @@ export const useSettingStore = defineStore('setting', () => { return versionedDefault } - return typeof param.defaultValue === 'function' - ? param.defaultValue() - : param.defaultValue + const defaultValue = param.defaultValue + return typeof defaultValue === 'function' + ? (defaultValue as () => Settings[K])() + : defaultValue } function getVersionedDefaultValue< diff --git a/src/platform/settings/types.ts b/src/platform/settings/types.ts index 9bd48fc8c..021fac375 100644 --- a/src/platform/settings/types.ts +++ b/src/platform/settings/types.ts @@ -16,21 +16,21 @@ type SettingInputType = type SettingCustomRenderer = ( name: string, - setter: (v: any) => void, - value: any, - attrs: any + setter: (v: unknown) => void, + value: unknown, + attrs?: Record ) => HTMLElement export interface SettingOption { text: string - value?: any + value?: string | number } -export interface SettingParams extends FormItem { +export interface SettingParams extends FormItem { id: keyof Settings - defaultValue: any | (() => any) + defaultValue: TValue | (() => TValue) defaultsByInstallVersion?: Record<`${number}.${number}.${number}`, TValue> - onChange?: (newValue: any, oldValue?: any) => void + onChange?: (newValue: TValue, oldValue?: TValue) => void // By default category is id.split('.'). However, changing id to assign // new category has poor backward compatibility. Use this field to overwrite // default category from id. @@ -38,8 +38,7 @@ export interface SettingParams extends FormItem { category?: string[] experimental?: boolean deprecated?: boolean - // Deprecated values are mapped to new values. - migrateDeprecatedValue?: (value: any) => any + migrateDeprecatedValue?: (value: TValue) => TValue // Version of the setting when it was added versionAdded?: string // Version of the setting when it was last modified @@ -57,7 +56,7 @@ export interface FormItem { name: string type: SettingInputType | SettingCustomRenderer tooltip?: string - attrs?: Record + attrs?: Record options?: Array } diff --git a/src/platform/telemetry/types.ts b/src/platform/telemetry/types.ts index 5b5e0f9fc..a707069a4 100644 --- a/src/platform/telemetry/types.ts +++ b/src/platform/telemetry/types.ts @@ -12,6 +12,8 @@ * 3. Check dist/assets/*.js files contain no tracking code */ +import type { AuditLog } from '@/services/customerEventsService' + /** * Authentication metadata for sign-up tracking */ @@ -276,7 +278,7 @@ export interface TelemetryProvider { // Credit top-up tracking (composition with internal utilities) startTopupTracking(): void - checkForCompletedTopup(events: any[] | undefined | null): boolean + checkForCompletedTopup(events: AuditLog[] | undefined | null): boolean clearTopupTracking(): void // Survey flow events diff --git a/src/platform/workflow/validation/schemas/workflowSchema.ts b/src/platform/workflow/validation/schemas/workflowSchema.ts index cc73a3928..558ef819d 100644 --- a/src/platform/workflow/validation/schemas/workflowSchema.ts +++ b/src/platform/workflow/validation/schemas/workflowSchema.ts @@ -466,14 +466,14 @@ type SubgraphDefinition = z.infer * Type guard to check if an object is a SubgraphDefinition. * This helps TypeScript understand the type when z.lazy() breaks inference. */ -export function isSubgraphDefinition(obj: any): obj is SubgraphDefinition { +export function isSubgraphDefinition(obj: unknown): obj is SubgraphDefinition { return ( - obj && + obj !== null && typeof obj === 'object' && 'id' in obj && 'name' in obj && 'nodes' in obj && - Array.isArray(obj.nodes) && + Array.isArray((obj as SubgraphDefinition).nodes) && 'inputNode' in obj && 'outputNode' in obj ) @@ -514,6 +514,7 @@ export async function validateComfyWorkflow( */ const zNodeInputValue = z.union([ // For widget values (can be any type) + z.any(), // For node links [nodeId, slotIndex] z.tuple([zNodeId, zSlotIndex]) diff --git a/src/schemas/apiSchema.ts b/src/schemas/apiSchema.ts index 50bf0813d..224ceb0df 100644 --- a/src/schemas/apiSchema.ts +++ b/src/schemas/apiSchema.ts @@ -28,10 +28,13 @@ const zOutputs = z audio: z.array(zResultItem).optional(), images: z.array(zResultItem).optional(), video: z.array(zResultItem).optional(), - animated: z.array(z.boolean()).optional() + animated: z.array(z.boolean()).optional(), + text: z.union([z.string(), z.array(z.string())]).optional() }) .passthrough() +export type NodeExecutionOutput = z.infer + // WS messages const zStatusWsMessageStatus = z.object({ exec_info: z.object({ diff --git a/src/schemas/nodeDefSchema.ts b/src/schemas/nodeDefSchema.ts index 867ee46ba..bb36da228 100644 --- a/src/schemas/nodeDefSchema.ts +++ b/src/schemas/nodeDefSchema.ts @@ -267,7 +267,7 @@ export type ComboInputSpecV2 = z.infer export type InputSpec = z.infer export function validateComfyNodeDef( - data: any, + data: unknown, onError: (error: string) => void = console.warn ): ComfyNodeDef | null { const result = zComfyNodeDef.safeParse(data) diff --git a/src/types/extensionTypes.ts b/src/types/extensionTypes.ts index 2c96faa05..7061a9b15 100644 --- a/src/types/extensionTypes.ts +++ b/src/types/extensionTypes.ts @@ -67,7 +67,7 @@ export interface ToastMessageOptions { /** * Detail content of the message. */ - detail?: any | undefined + detail?: string /** * Whether the message can be closed manually using the close icon. * @defaultValue true @@ -84,11 +84,12 @@ export interface ToastMessageOptions { /** * Style class of the message. */ - styleClass?: any + styleClass?: string | string[] | Record /** * Style class of the content. + * Matches PrimeVue Toast API which accepts Vue class bindings. */ - contentStyleClass?: any + contentStyleClass?: string | string[] | Record } export type ToastManager = { @@ -107,8 +108,8 @@ export interface ExtensionManager { dialog: ReturnType command: CommandManager setting: { - get: (id: string) => any - set: (id: string, value: any) => void + get: (id: string) => T | undefined + set: (id: string, value: T) => void } } diff --git a/src/types/litegraph-augmentation.d.ts b/src/types/litegraph-augmentation.d.ts index f6b4aaf42..0b283b158 100644 --- a/src/types/litegraph-augmentation.d.ts +++ b/src/types/litegraph-augmentation.d.ts @@ -7,6 +7,7 @@ import type { } from '@/lib/litegraph/src/litegraph' import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets' import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema' +import type { NodeExecutionOutput } from '@/schemas/apiSchema' import type { ComfyNodeDef as ComfyNodeDefV2 } from '@/schemas/nodeDef/nodeDefSchemaV2' import type { ComfyNodeDef as ComfyNodeDefV1 } from '@/schemas/nodeDefSchema' import type { DOMWidget, DOMWidgetOptions } from '@/scripts/domWidget' @@ -94,7 +95,12 @@ declare module '@/lib/litegraph/src/litegraph' { */ onAfterGraphConfigured?(): void onGraphConfigured?(): void - onExecuted?(output: any): void + /** + * Callback fired when node execution completes. + * Output contains known media properties (images, audio, video) plus + * arbitrary node-specific outputs (text, ui, custom properties). + */ + onExecuted?(output: NodeExecutionOutput): void onNodeCreated?(this: LGraphNode): void /** @deprecated groupNode */ setInnerNodes?(nodes: LGraphNode[]): void diff --git a/src/types/metadataTypes.ts b/src/types/metadataTypes.ts index 943e39ae7..72f3a7293 100644 --- a/src/types/metadataTypes.ts +++ b/src/types/metadataTypes.ts @@ -69,15 +69,15 @@ export type GltfChunkHeader = { type GltfExtras = { workflow?: string | object prompt?: string | object - [key: string]: any + [key: string]: unknown } export type GltfJsonData = { asset?: { extras?: GltfExtras - [key: string]: any + [key: string]: unknown } - [key: string]: any + [key: string]: unknown } /**