mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-24 22:58:08 +00:00
Cascades the foundation fix (8564a19dc7) into the published API
snapshot. NodeMode JSDoc now correctly maps numeric slots to
LGraphEventMode names (was wrong for slots 1-4 in prior snapshot).
Other diff churn is whitespace/format-only from a fresh dts build.
473 lines
14 KiB
TypeScript
473 lines
14 KiB
TypeScript
import { AsyncHandler, Handler, Unsubscribe } from './events'
|
|
import { WidgetHandle, WidgetOptions } from './widget'
|
|
import { NodeEntityId } from '../world/entityIds'
|
|
export type { NodeEntityId }
|
|
/**
|
|
* A 2D point as `[x, y]`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export type Point = [x: number, y: number]
|
|
/**
|
|
* A 2D size as `[width, height]`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export type Size = [width: number, height: number]
|
|
/**
|
|
* LiteGraph node execution mode.
|
|
*
|
|
* Numeric values match `LGraphEventMode` in the LiteGraph runtime.
|
|
*
|
|
* - `0` — `ALWAYS`: execute every run (default).
|
|
* - `1` — `ON_EVENT`: legacy slot for the dead trigger/action subsystem;
|
|
* has no behavioural effect in the current scheduler. Reserved for ABI
|
|
* compatibility — do not use in new extensions.
|
|
* - `2` — `NEVER`: muted; node is skipped during execution.
|
|
* - `3` — `ON_TRIGGER`: legacy slot for the dead trigger/action subsystem;
|
|
* gated behind `LiteGraph.do_add_triggers_slots` (always `false`). Reserved
|
|
* for ABI compatibility — do not use in new extensions.
|
|
* - `4` — `BYPASS`: passthrough; inputs are forwarded to outputs without
|
|
* running the node.
|
|
*
|
|
* Practical extension code should use `0` (always) or `2` (never/muted) or
|
|
* `4` (bypass). Slots `1` and `3` are documented for completeness but their
|
|
* runtime semantics are pending the AUDIT-LG trigger-subsystem cleanup.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export type NodeMode = 0 | 1 | 2 | 3 | 4
|
|
/**
|
|
* Direction of a slot on a node.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export type SlotDirection = 'input' | 'output'
|
|
/**
|
|
* Read-only snapshot of a single slot (input or output) on a node.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface SlotInfo {
|
|
/** Branded entity ID for this slot. */
|
|
readonly entityId: SlotEntityId
|
|
/** Slot name as declared in `INPUT_TYPES` or `addInput`/`addOutput`. */
|
|
readonly name: string
|
|
/** Slot type string (e.g. `'IMAGE'`, `'LATENT'`, `'*'`). */
|
|
readonly type: string
|
|
/** Whether this is an input or output slot. */
|
|
readonly direction: SlotDirection
|
|
/** The node this slot belongs to. */
|
|
readonly nodeEntityId: NodeEntityId
|
|
}
|
|
/**
|
|
* Branded entity ID for slots. Prevents mixing slot IDs with node/widget IDs.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export type SlotEntityId = number & {
|
|
readonly __brand: 'SlotEntityId'
|
|
}
|
|
/**
|
|
* Payload for `node.on('executed', handler)`.
|
|
*
|
|
* Replaces the v1 `nodeType.prototype.onExecuted` patching pattern.
|
|
*
|
|
* @stability stable
|
|
* @example
|
|
* ```ts
|
|
* node.on('executed', (e) => {
|
|
* const text = e.output['text'] as string[]
|
|
* previewWidget.setValue(text.join('\n'))
|
|
* })
|
|
* ```
|
|
*/
|
|
export interface NodeExecutedEvent {
|
|
/** The backend execution output for this node. Shape varies by node type. */
|
|
readonly output: Record<string, unknown>
|
|
}
|
|
/**
|
|
* Payload for `node.on('connected', handler)`.
|
|
*
|
|
* Replaces `nodeType.prototype.onConnectInput` / `onConnectOutput` and
|
|
* `nodeType.prototype.onConnectionsChange` patching.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface NodeConnectedEvent {
|
|
/** The local slot that was connected. */
|
|
readonly slot: SlotInfo
|
|
/** The remote slot on the other node. */
|
|
readonly remote: SlotInfo
|
|
}
|
|
/**
|
|
* Payload for `node.on('disconnected', handler)`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface NodeDisconnectedEvent {
|
|
/** The local slot that was disconnected. */
|
|
readonly slot: SlotInfo
|
|
}
|
|
/**
|
|
* Payload for `node.on('positionChanged', handler)`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface NodePositionChangedEvent {
|
|
/** The new position. */
|
|
readonly pos: Point
|
|
}
|
|
/**
|
|
* Payload for `node.on('sizeChanged', handler)`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface NodeSizeChangedEvent {
|
|
/** The new size. */
|
|
readonly size: Size
|
|
}
|
|
/**
|
|
* Payload for `node.on('modeChanged', handler)`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
export interface NodeModeChangedEvent {
|
|
/** The new execution mode. */
|
|
readonly mode: NodeMode
|
|
}
|
|
/**
|
|
* Payload for `node.on('beforeSerialize', handler)`.
|
|
*
|
|
* The node-level equivalent of `WidgetBeforeSerializeEvent`. Replaces both
|
|
* `node.onSerialize` and `nodeType.prototype.serialize` patching patterns
|
|
* (v1 S2.N6, S2.N15 touch-points).
|
|
*
|
|
* Mutate `event.data` in place to append extra fields (replaces `onSerialize`).
|
|
* Call `event.replace(fn)` to wrap the entire serialized object (replaces
|
|
* `prototype.serialize = function(){ const r = orig.call(this); … }`).
|
|
*
|
|
* @stability experimental
|
|
* @example
|
|
* ```ts
|
|
* // Append a field
|
|
* node.on('beforeSerialize', (e) => {
|
|
* e.data['my_extra'] = computeExtra()
|
|
* })
|
|
*
|
|
* // Wrap the serialized object
|
|
* node.on('beforeSerialize', (e) => {
|
|
* e.replace((orig) => ({ ...orig, wrapped: true }))
|
|
* })
|
|
* ```
|
|
*/
|
|
export interface NodeBeforeSerializeEvent {
|
|
/** Which serialization path triggered this. */
|
|
readonly context: 'workflow' | 'prompt' | 'clone' | 'subgraph-promote'
|
|
/**
|
|
* The mutable serialized node object. Mutate in place to append fields.
|
|
* Type intentionally loose — the exact shape is `ISerialisedNode`.
|
|
*/
|
|
readonly data: Record<string, unknown>
|
|
/**
|
|
* Replace the serialized object by providing a transform function.
|
|
* `fn` receives the current `data` and should return the replacement.
|
|
* Calling this multiple times chains: each call's `fn` receives the
|
|
* previous call's output.
|
|
*/
|
|
replace(fn: (orig: Record<string, unknown>) => Record<string, unknown>): void
|
|
}
|
|
/**
|
|
* Options for `NodeHandle.addDOMWidget()`.
|
|
*
|
|
* @stability experimental
|
|
*/
|
|
export interface DOMWidgetOptions {
|
|
/** Unique widget name within this node. */
|
|
name: string
|
|
/** The DOM element to embed in the node widget area. */
|
|
element: HTMLElement
|
|
/** Reserved height in pixels. Defaults to `element.offsetHeight` at mount time. */
|
|
height?: number
|
|
}
|
|
/**
|
|
* Controlled surface for node access. Reads query the ECS World; writes
|
|
* dispatch commands. Events are Vue-reactive watches on World components.
|
|
*
|
|
* @stability stable
|
|
* @example
|
|
* ```ts
|
|
* import { defineNodeExtension } from '@comfyorg/extension-api'
|
|
*
|
|
* export default defineNodeExtension({
|
|
* name: 'my-size-enforcer',
|
|
* nodeTypes: ['MyCustomNode'],
|
|
*
|
|
* nodeCreated(node) {
|
|
* const [w, h] = node.getSize()
|
|
* node.setSize([Math.max(w, 300), Math.max(h, 200)])
|
|
*
|
|
* node.on('executed', (e) => {
|
|
* console.log('output:', e.output)
|
|
* })
|
|
* }
|
|
* })
|
|
* ```
|
|
*/
|
|
export interface NodeHandle {
|
|
/**
|
|
* Stable entity ID for this node. Branded to prevent mixing with
|
|
* `WidgetEntityId` at compile time.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
readonly entityId: NodeEntityId
|
|
/**
|
|
* The LiteGraph node type string (e.g. `'KSampler'`).
|
|
* Read-only invariant: set at construction, never changes.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
readonly type: string
|
|
/**
|
|
* The ComfyUI backend class name (e.g. `'KSampler'`).
|
|
* Equal to `type` for most nodes; differs for reroute/virtual nodes.
|
|
* Read-only invariant.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
readonly comfyClass: string
|
|
/**
|
|
* Returns the node's current canvas position as `[x, y]`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getPosition(): Point
|
|
/**
|
|
* Moves the node to a new canvas position. Dispatches a `MoveNode` command.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
setPosition(pos: Point): void
|
|
/**
|
|
* Returns the node's current size as `[width, height]`.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getSize(): Size
|
|
/**
|
|
* Resizes the node. Dispatches a `ResizeNode` command.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
setSize(size: Size): void
|
|
/**
|
|
* Returns the node's display title. Defaults to the node type string.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getTitle(): string
|
|
/**
|
|
* Sets the node's display title. Dispatches a `SetNodeVisual` command.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
setTitle(title: string): void
|
|
/**
|
|
* Returns `true` if the node is currently selected on the canvas.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
isSelected(): boolean
|
|
/**
|
|
* Returns the node's current execution mode.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getMode(): NodeMode
|
|
/**
|
|
* Sets the node's execution mode. Dispatches a `SetNodeMode` command.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
setMode(mode: NodeMode): void
|
|
/**
|
|
* Returns a per-node-instance property by key.
|
|
*
|
|
* In v2, prefer routing persistent state through widget values or
|
|
* `beforeSerialize` events. `node.properties` is kept as a migration shim
|
|
* for v1 extensions that used it for per-instance widget config (e.g. min/max).
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getProperty<T = unknown>(key: string): T | undefined
|
|
/**
|
|
* Returns a copy of all per-node-instance properties.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
getProperties(): Record<string, unknown>
|
|
/**
|
|
* Sets a per-node-instance property. Dispatches a `SetNodeProperty` command.
|
|
*
|
|
* In v2, prefer `widget.setOption(key, value)` for widget-scoped per-instance
|
|
* config (it persists to the `widget_options` sidecar in the workflow JSON).
|
|
*
|
|
* @stability stable
|
|
*/
|
|
setProperty(key: string, value: unknown): void
|
|
/**
|
|
* Returns a `WidgetHandle` for the named widget, or `undefined` if no such
|
|
* widget exists on this node.
|
|
*
|
|
* @stability stable
|
|
* @example
|
|
* ```ts
|
|
* const steps = node.widget('steps')
|
|
* if (steps) steps.setValue(20)
|
|
* ```
|
|
*/
|
|
widget(name: string): WidgetHandle | undefined
|
|
/**
|
|
* Returns all widgets on this node as `WidgetHandle` instances.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
widgets(): readonly WidgetHandle[]
|
|
/**
|
|
* Adds a new widget to this node.
|
|
*
|
|
* @param type - Widget type string (e.g. `'INT'`, `'STRING'`, `'COMBO'`).
|
|
* @param name - Unique widget name on this node.
|
|
* @param defaultValue - Initial value.
|
|
* @param options - Optional type-specific options.
|
|
* @returns The new `WidgetHandle`.
|
|
* @stability stable
|
|
*/
|
|
addWidget(
|
|
type: string,
|
|
name: string,
|
|
defaultValue: unknown,
|
|
options?: Partial<WidgetOptions>
|
|
): WidgetHandle
|
|
/**
|
|
* Adds a DOM-backed widget to this node.
|
|
*
|
|
* Replaces the v1 `node.addDOMWidget(name, type, element, opts)` pattern.
|
|
* The runtime automatically:
|
|
* - Reserves node height for the element (via auto-computeSize integration).
|
|
* - Removes the element from the DOM when the node is removed.
|
|
* - Includes the widget in `NodeHandle.widgets()`.
|
|
*
|
|
* Use `WidgetHandle.setHeight(px)` to resize the reservation after initial mount.
|
|
*
|
|
* @param opts.name - Unique widget name on this node.
|
|
* @param opts.element - The DOM element to embed.
|
|
* @param opts.height - Initial reserved height in pixels. Defaults to `element.offsetHeight`.
|
|
* @returns A `WidgetHandle` for the registered DOM widget.
|
|
* @stability experimental
|
|
*/
|
|
addDOMWidget(opts: DOMWidgetOptions): WidgetHandle
|
|
/**
|
|
* Returns all input slots on this node.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
inputs(): readonly SlotInfo[]
|
|
/**
|
|
* Returns all output slots on this node.
|
|
*
|
|
* @stability stable
|
|
*/
|
|
outputs(): readonly SlotInfo[]
|
|
/**
|
|
* Subscribe to node removal (graph deletion, not subgraph promotion).
|
|
*
|
|
* Replaces the v1 `nodeType.prototype.onRemoved` patching pattern.
|
|
* Does NOT fire on subgraph promotion — the node's entity ID is preserved
|
|
* across promotion (see D9 Phase A notes and D12).
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'removed', handler: Handler<void>): Unsubscribe
|
|
/**
|
|
* Subscribe to backend execution completion for this node.
|
|
*
|
|
* Replaces the v1 `nodeType.prototype.onExecuted` patching pattern (the
|
|
* most widely used anti-pattern per R4-P3; 5+ confirmed repos).
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'executed', handler: Handler<NodeExecutedEvent>): Unsubscribe
|
|
/**
|
|
* Subscribe to workflow hydration (node loaded from a saved workflow).
|
|
*
|
|
* Replaces the v1 `nodeType.prototype.onConfigure` / `loadedGraphNode`
|
|
* patterns. Fires after all widget values are restored from the workflow JSON.
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'configured', handler: Handler<void>): Unsubscribe
|
|
/**
|
|
* Subscribe to slot connection events.
|
|
*
|
|
* Replaces `nodeType.prototype.onConnectInput`, `onConnectOutput`, and
|
|
* `onConnectionsChange` patching patterns (R4-P4: six distinct signatures
|
|
* in the wild — this single typed event resolves the confusion).
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'connected', handler: Handler<NodeConnectedEvent>): Unsubscribe
|
|
/**
|
|
* Subscribe to slot disconnection events.
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(
|
|
event: 'disconnected',
|
|
handler: Handler<NodeDisconnectedEvent>
|
|
): Unsubscribe
|
|
/**
|
|
* Subscribe to canvas position changes.
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(
|
|
event: 'positionChanged',
|
|
handler: Handler<NodePositionChangedEvent>
|
|
): Unsubscribe
|
|
/**
|
|
* Subscribe to node size changes.
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'sizeChanged', handler: Handler<NodeSizeChangedEvent>): Unsubscribe
|
|
/**
|
|
* Subscribe to execution mode changes.
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability stable
|
|
*/
|
|
on(event: 'modeChanged', handler: Handler<NodeModeChangedEvent>): Unsubscribe
|
|
/**
|
|
* Subscribe to node serialization. Async-capable.
|
|
*
|
|
* Replaces `nodeType.prototype.onSerialize` and `nodeType.prototype.serialize`
|
|
* patching patterns. Collapses four v1 serialization surfaces to one (D7 Part 4).
|
|
*
|
|
* @returns A cleanup function to remove the listener.
|
|
* @stability experimental
|
|
*/
|
|
on(
|
|
event: 'beforeSerialize',
|
|
handler: AsyncHandler<NodeBeforeSerializeEvent>
|
|
): Unsubscribe
|
|
}
|