mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-21 21:09:00 +00:00
docs(ext-api): refresh @example blocks + deprecate notify (W17.C/D/E)
- W17.C: refresh 5 stale @example blocks (types.ts, lifecycle.ts, node.ts,
imperatives.ts ×2) — replace deprecated `async setup()` with
`setup() { onMounted(...) }`; remove A1-removed `node.getWidget` from
defineNode + NodeHandle.on migration examples; align imperatives examples
with W17.B notify-toast verdict.
- W17.D: author ~37 new @example blocks across 9 files for sparse exports
surfaced by W17.A audit. Pure JSDoc — zero exported-type diff.
- W17.E: add @deprecated JSDoc to notify() + NotifyOptions per
D-notify-toast-consolidation (W17.B verdict (a) soft-deprecate).
Pure JSDoc — no signature, type, or export changes.
Phase A surface remains FROZEN at ee0537fdb5 (foundation surface SHA
unchanged; only @example / @deprecated text differs).
See research/dashboard-snippet-audit-2026-05-21.md (W17.A) for full
per-edit rationale.
This commit is contained in:
@@ -22,6 +22,15 @@ export type Handler<E> = (event: E) => void
|
||||
* support async handling (currently only `beforeSerialize`).
|
||||
*
|
||||
* @typeParam E - The event payload type.
|
||||
* @example
|
||||
* ```ts
|
||||
* import type { AsyncHandler, WidgetBeforeSerializeEvent } from '@comfyorg/extension-api'
|
||||
*
|
||||
* const handler: AsyncHandler<WidgetBeforeSerializeEvent> = async (e) => {
|
||||
* const frame = await captureFrame()
|
||||
* e.setSerializedValue(frame)
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export type AsyncHandler<E> = (event: E) => void | Promise<void>
|
||||
|
||||
@@ -76,12 +85,24 @@ import { getCurrentExtensionInstance } from '@/services/extension-api-service'
|
||||
export interface GraphEventPayloads {
|
||||
[event: string]: unknown
|
||||
}
|
||||
/**
|
||||
* See {@link GraphEventPayloads | the augmentation example} —
|
||||
* augment this interface the same way to narrow `execution.*` payloads.
|
||||
*/
|
||||
export interface ExecutionEventPayloads {
|
||||
[event: string]: unknown
|
||||
}
|
||||
/**
|
||||
* See {@link GraphEventPayloads | the augmentation example} —
|
||||
* augment this interface the same way to narrow `server.*` payloads.
|
||||
*/
|
||||
export interface ServerEventPayloads {
|
||||
[event: string]: unknown
|
||||
}
|
||||
/**
|
||||
* See {@link GraphEventPayloads | the augmentation example} —
|
||||
* augment this interface the same way to narrow `workbench.*` payloads.
|
||||
*/
|
||||
export interface WorkbenchEventPayloads {
|
||||
[event: string]: unknown
|
||||
}
|
||||
@@ -179,6 +200,21 @@ export const graph: EventNamespace<GraphEventPayloads> = makeNamespace(
|
||||
*
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineExtension, onMounted, execution } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineExtension({
|
||||
* name: 'my-ext',
|
||||
* setup() {
|
||||
* onMounted(() => {
|
||||
* execution.on('start', (e) => console.log('run started', e))
|
||||
* execution.on('progress', (e) => console.log('progress', e))
|
||||
* execution.on('end', () => console.log('run done'))
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export const execution: EventNamespace<ExecutionEventPayloads> = makeNamespace(
|
||||
(evt) => `execution_${evt}`
|
||||
@@ -194,6 +230,19 @@ export const execution: EventNamespace<ExecutionEventPayloads> = makeNamespace(
|
||||
*
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineExtension, onMounted, server } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineExtension({
|
||||
* name: 'my-ext',
|
||||
* setup() {
|
||||
* onMounted(() => {
|
||||
* server.on('reconnected', () => console.log('server back online'))
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export const server: EventNamespace<ServerEventPayloads> = makeNamespace(
|
||||
(evt) => evt
|
||||
@@ -209,6 +258,19 @@ export const server: EventNamespace<ServerEventPayloads> = makeNamespace(
|
||||
*
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineExtension, onMounted, workbench } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineExtension({
|
||||
* name: 'my-ext',
|
||||
* setup() {
|
||||
* onMounted(() => {
|
||||
* workbench.on('notification', (e) => console.log('workbench notif', e))
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export const workbench: EventNamespace<WorkbenchEventPayloads> = makeNamespace(
|
||||
(evt) => `workbench:${evt}`
|
||||
|
||||
@@ -11,6 +11,39 @@
|
||||
|
||||
export type { NodeLocatorId, NodeExecutionId } from '@/types/nodeIdentification'
|
||||
|
||||
/**
|
||||
* Node identity round-trip helpers. Create/parse branded `NodeLocatorId` and
|
||||
* `NodeExecutionId` values, or narrow an `unknown` to one with the type
|
||||
* guards. Use these instead of raw string manipulation so future changes to
|
||||
* the identity scheme stay transparent.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* createNodeLocatorId,
|
||||
* parseNodeLocatorId,
|
||||
* isNodeLocatorId,
|
||||
* createNodeExecutionId,
|
||||
* parseNodeExecutionId,
|
||||
* isNodeExecutionId
|
||||
* } from '@comfyorg/extension-api'
|
||||
*
|
||||
* // Construct
|
||||
* const locator = createNodeLocatorId(graphUuid, localId)
|
||||
* const execId = createNodeExecutionId(locator, runTag)
|
||||
*
|
||||
* // Narrow
|
||||
* if (isNodeLocatorId(maybe)) {
|
||||
* const parts = parseNodeLocatorId(maybe)
|
||||
* console.log(parts.graphUuid, parts.localId)
|
||||
* }
|
||||
*
|
||||
* if (isNodeExecutionId(maybe)) {
|
||||
* const parts = parseNodeExecutionId(maybe)
|
||||
* console.log(parts.locator, parts.runTag)
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export {
|
||||
isNodeLocatorId,
|
||||
isNodeExecutionId,
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
* import {
|
||||
* defineExtension,
|
||||
* onMounted,
|
||||
* toast,
|
||||
* notify
|
||||
* toast
|
||||
* } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineExtension({
|
||||
@@ -25,7 +24,6 @@
|
||||
* setup() {
|
||||
* onMounted(() => {
|
||||
* toast.show({ severity: 'info', summary: 'Ready' })
|
||||
* notify({ kind: 'info', message: 'Loaded' })
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
@@ -44,6 +42,8 @@ import type { ToastMessageOptions } from '@/types/extensionTypes'
|
||||
* {@link toast}. `kind` maps onto PrimeVue toast severities; `message` maps
|
||||
* to `summary`; `detail` is optional supplementary text.
|
||||
*
|
||||
* @deprecated Use {@link ToastMessageOptions} via `toast.show(...)`. See
|
||||
* D-notify-toast-consolidation.
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
*/
|
||||
@@ -100,11 +100,21 @@ export const toast: {
|
||||
*
|
||||
* Fire-and-forget.
|
||||
*
|
||||
* @deprecated Use {@link toast.show} — `notify` is a 1:1 wrapper sharing the
|
||||
* same transport. See D-notify-toast-consolidation.
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* notify({ kind: 'error', message: 'Workflow failed', detail: err.message })
|
||||
* // `notify` is deprecated — prefer `toast.show` directly. See
|
||||
* // D-notify-toast-consolidation.
|
||||
* import { toast } from '@comfyorg/extension-api'
|
||||
*
|
||||
* toast.show({
|
||||
* severity: 'error',
|
||||
* summary: 'Workflow failed',
|
||||
* detail: err.message
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export function notify(opts: NotifyOptions): void {
|
||||
|
||||
@@ -57,19 +57,17 @@ import type {
|
||||
* ```ts
|
||||
* import { defineNode } from '@comfyorg/extension-api'
|
||||
*
|
||||
* // Assumes the Python `PreviewAny` node declares a hidden, read-only
|
||||
* // STRING input named `preview` in INPUT_TYPES. Runtime widget addition
|
||||
* // is forbidden per AXIOMS.md A15 / D-ban-runtime-addwidget — declare in
|
||||
* // INPUT_TYPES, then bind via getWidget().
|
||||
* // Per AXIOMS.md §A1, nodes cannot enumerate widgets. To attach
|
||||
* // per-widget behavior, register a widget type via `defineWidget` and
|
||||
* // use the mount context's `ctx.widget` handle. This example reacts to
|
||||
* // node-level execution only.
|
||||
* export default defineNode({
|
||||
* name: 'Comfy.PreviewAny',
|
||||
* nodeTypes: ['PreviewAny'],
|
||||
* name: 'my-org.executed-logger',
|
||||
* nodeTypes: ['KSampler'],
|
||||
*
|
||||
* nodeCreated(node) {
|
||||
* const preview = node.getWidget('preview')
|
||||
* if (!preview) return
|
||||
* node.on('executed', (e) => {
|
||||
* preview.setValue(String(e.output['text'] ?? ''))
|
||||
* console.log('node executed:', e.output)
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
@@ -183,6 +181,30 @@ export declare function defineWidget(
|
||||
* setup context) throws in development and silently no-ops in production.
|
||||
*
|
||||
* See {@link onMounted} for full usage examples.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* defineSidebarTab,
|
||||
* onMounted,
|
||||
* onUnmounted,
|
||||
* onActivated,
|
||||
* onDeactivated
|
||||
* } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineSidebarTab({
|
||||
* id: 'my-tab',
|
||||
* title: 'My Tab',
|
||||
* type: 'vue',
|
||||
* component: MyTab,
|
||||
* setup() {
|
||||
* onMounted(() => console.log('tab mounted'))
|
||||
* onActivated(() => console.log('tab shown'))
|
||||
* onDeactivated(() => console.log('tab hidden'))
|
||||
* onUnmounted(() => console.log('tab unmounted'))
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export {
|
||||
onBeforeMount,
|
||||
|
||||
@@ -29,6 +29,14 @@ export type { NodeEntityId }
|
||||
* **Immutable tuple.** Attempts to
|
||||
* mutate via `node.getPosition()[0] = X` raise a TypeScript error. Use
|
||||
* {@link NodeHandle.setPosition} to move the node.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import type { Point } from '@comfyorg/extension-api'
|
||||
*
|
||||
* // Per-pixel mouse coordinate from a canvas event
|
||||
* const cursor: Point = [event.canvasX, event.canvasY]
|
||||
* ```
|
||||
*/
|
||||
export type Point = readonly [x: number, y: number]
|
||||
|
||||
@@ -38,6 +46,13 @@ export type Point = readonly [x: number, y: number]
|
||||
* **Immutable tuple.** Attempts to
|
||||
* mutate via `node.getSize()[0] = X` raise a TypeScript error. Use
|
||||
* {@link NodeHandle.setSize} to resize the node.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import type { Size } from '@comfyorg/extension-api'
|
||||
*
|
||||
* const target: Size = [320, 240]
|
||||
* ```
|
||||
*/
|
||||
export type Size = readonly [width: number, height: number]
|
||||
|
||||
@@ -368,15 +383,19 @@ export interface NodeHandle {
|
||||
*
|
||||
* // AFTER (recommended — widget-level, schema-declared)
|
||||
* // Declare `_my_state` in the Python node's INPUT_TYPES as a hidden
|
||||
* // STRING input; the widget will exist automatically. Then attach
|
||||
* // the serialization transform to the widget:
|
||||
* const stateWidget = node.getWidget('_my_state')!
|
||||
* stateWidget.on('beforeSerialize', (e) => {
|
||||
* e.setSerializedValue(JSON.stringify(computeState()))
|
||||
* // STRING input. Then attach the serialization transform inside
|
||||
* // `defineWidget({mount})` — `ctx.widget` is the only legal handle:
|
||||
* import { defineWidget } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineWidget({
|
||||
* name: 'my-org.state-shim',
|
||||
* type: 'STRING',
|
||||
* mount(_host, ctx) {
|
||||
* ctx.widget.on('beforeSerialize', (e) => {
|
||||
* e.setSerializedValue(JSON.stringify(computeState()))
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* // Note: runtime widget addition is forbidden per AXIOMS.md A15 /
|
||||
* // D-ban-runtime-addwidget — declare in INPUT_TYPES, do not call
|
||||
* // node.addWidget().
|
||||
* ```
|
||||
*
|
||||
* @returns A cleanup function to remove the listener.
|
||||
|
||||
@@ -59,6 +59,20 @@ import type {
|
||||
*
|
||||
* @publicAPI
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineSidebarTab, type DisposableHandle } from '@comfyorg/extension-api'
|
||||
*
|
||||
* const handle: DisposableHandle = defineSidebarTab({
|
||||
* id: 'my-tab',
|
||||
* title: 'My Tab',
|
||||
* type: 'vue',
|
||||
* component: MyTab
|
||||
* })
|
||||
*
|
||||
* // Later: tear down
|
||||
* handle.dispose()
|
||||
* ```
|
||||
*/
|
||||
export interface DisposableHandle {
|
||||
dispose(): void
|
||||
|
||||
@@ -17,14 +17,50 @@
|
||||
// (ExtensionSlot.vue) import them directly from '@/types/extensionTypes'.
|
||||
export type {
|
||||
// Pre-existing types (unchanged shape)
|
||||
/**
|
||||
* Options bag for {@link defineSidebarTab}.
|
||||
* @see {@link defineSidebarTab} for a usage example.
|
||||
*/
|
||||
SidebarTabExtension,
|
||||
/**
|
||||
* Options bag for {@link defineBottomPanelTab}.
|
||||
* @see {@link defineBottomPanelTab} for a usage example.
|
||||
*/
|
||||
BottomPanelExtension,
|
||||
/**
|
||||
* Options bag for {@link toast.show} / {@link toast.remove}.
|
||||
* @see {@link toast} for a usage example.
|
||||
*/
|
||||
ToastMessageOptions,
|
||||
/**
|
||||
* Manager interface backing the {@link toast} surface.
|
||||
* @see {@link toast} for a usage example.
|
||||
*/
|
||||
ToastManager,
|
||||
// Net-new shell-UI arg types
|
||||
/**
|
||||
* Options bag for {@link defineCommand}.
|
||||
* @see {@link defineCommand} for a usage example.
|
||||
*/
|
||||
CommandDefinition,
|
||||
/**
|
||||
* Options bag for {@link defineHotkey}.
|
||||
* @see {@link defineHotkey} for a usage example.
|
||||
*/
|
||||
HotkeyExtension,
|
||||
/**
|
||||
* Options bag for {@link defineAboutBadge}.
|
||||
* @see {@link defineAboutBadge} for a usage example.
|
||||
*/
|
||||
AboutBadgeExtension,
|
||||
/**
|
||||
* Options bag for {@link defineSetting}.
|
||||
* @see {@link defineSetting} for a usage example.
|
||||
*/
|
||||
SettingDefinition,
|
||||
/**
|
||||
* Options bag for {@link defineToolbarButton}.
|
||||
* @see {@link defineToolbarButton} for a usage example.
|
||||
*/
|
||||
ToolbarButtonExtension
|
||||
} from '@/types/extensionTypes'
|
||||
|
||||
@@ -86,12 +86,14 @@ export interface NodeExtensionOptions {
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineExtension } from '@comfyorg/extension-api'
|
||||
* import { defineExtension, onMounted } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineExtension({
|
||||
* name: 'my-org.my-extension',
|
||||
* async setup() {
|
||||
* // App is ready; register commands, sidebar tabs, etc.
|
||||
* setup() {
|
||||
* onMounted(() => {
|
||||
* // App is ready; register commands, sidebar tabs, etc.
|
||||
* })
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
|
||||
@@ -25,6 +25,15 @@ export type { WidgetEntityId }
|
||||
/**
|
||||
* The union of all legal widget scalar values. Complex widgets (DOM, canvas)
|
||||
* may return their own serializable shapes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import type { WidgetValue } from '@comfyorg/extension-api'
|
||||
*
|
||||
* // `WidgetValue` is `string | number | boolean | null` — the four
|
||||
* // primitive-widget value shapes.
|
||||
* const val: WidgetValue = 42
|
||||
* ```
|
||||
*/
|
||||
export type WidgetValue = string | number | boolean | null
|
||||
|
||||
@@ -512,6 +521,20 @@ export interface WidgetHandle<T = WidgetValue> {
|
||||
* for those.
|
||||
*
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineWidget, type WidgetCleanup } from '@comfyorg/extension-api'
|
||||
*
|
||||
* defineWidget({
|
||||
* name: 'my-ext',
|
||||
* type: 'STRING',
|
||||
* mount(host): WidgetCleanup {
|
||||
* const input = document.createElement('input')
|
||||
* host.appendChild(input)
|
||||
* return () => input.remove()
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export type WidgetCleanup = () => void
|
||||
|
||||
@@ -571,6 +594,17 @@ export interface WidgetMountContext {
|
||||
* remount fires `ctx.onBeforeRemount` / `ctx.onAfterRemount` instead.
|
||||
*
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import type { WidgetMountFn } from '@comfyorg/extension-api'
|
||||
*
|
||||
* const mount: WidgetMountFn = (host, ctx) => {
|
||||
* const el = document.createElement('div')
|
||||
* el.textContent = String(ctx.widget.getValue() ?? '')
|
||||
* host.appendChild(el)
|
||||
* return () => el.remove()
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export type WidgetMountFn = (
|
||||
host: HTMLElement,
|
||||
|
||||
Reference in New Issue
Block a user