mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-24 14:45:36 +00:00
refactor(ext-api): rename defineNodeExtension → defineNode, defineWidgetExtension → defineWidget
Shorter function names improve ergonomics while maintaining clarity: - defineNode() - register node-scoped extensions - defineWidget() - register widget type extensions Old names kept as deprecated aliases for backwards compatibility. Will be removed in v1.0. Updates all docs, examples, tests, and internal references. Addresses review discussion item #4 from design-review-12142.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,14 +7,14 @@
|
||||
* Import directly — no dependency on `window.app` at module evaluation time:
|
||||
*
|
||||
* ```ts
|
||||
* import { defineNodeExtension, defineExtension } from '@comfyorg/extension-api'
|
||||
* import { defineNode, defineExtension } from '@comfyorg/extension-api'
|
||||
* ```
|
||||
*
|
||||
* ## API surface overview
|
||||
*
|
||||
* | Export | Purpose |
|
||||
* |--------|---------|
|
||||
* | `defineNodeExtension` | Register a node-scoped extension (the primary entry point) |
|
||||
* | `defineNode` | Register a node-scoped extension (the primary entry point) |
|
||||
* | `defineExtension` | Register an app-scoped extension (init, setup, shell UI) |
|
||||
* | `onNodeMounted`, `onNodeRemoved` | Implicit-context lifecycle hooks (call inside nodeCreated) |
|
||||
* | `NodeHandle` | Controlled access to node state and events |
|
||||
@@ -57,10 +57,13 @@ export type {
|
||||
// ── Registration function implementations ────────────────────────────────────
|
||||
// Runtime implementations live in the service; the types above are the
|
||||
// public contract. The barrel re-exports the concrete fns from the service
|
||||
// so `import { defineNodeExtension } from '@comfyorg/extension-api'` works
|
||||
// so `import { defineNode } from '@comfyorg/extension-api'` works
|
||||
// at both typecheck and runtime.
|
||||
export {
|
||||
defineExtension,
|
||||
defineNode,
|
||||
defineWidget,
|
||||
// Deprecated aliases (remove in v1.0)
|
||||
defineNodeExtension,
|
||||
defineWidgetExtension,
|
||||
startExtensionSystem
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Extension lifecycle — `defineExtension`, `defineNodeExtension`, and
|
||||
* Extension lifecycle — `defineExtension`, `defineNode`, and
|
||||
* the implicit-context lifecycle hooks (`onNodeMounted`, `onNodeRemoved`).
|
||||
*
|
||||
* Key behaviors:
|
||||
@@ -58,9 +58,9 @@ import type {
|
||||
* @publicAPI
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineNodeExtension } from '@comfyorg/extension-api'
|
||||
* import { defineNode } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineNodeExtension({
|
||||
* export default defineNode({
|
||||
* name: 'Comfy.PreviewAny',
|
||||
* nodeTypes: ['PreviewAny'],
|
||||
*
|
||||
@@ -75,6 +75,11 @@ import type {
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export declare function defineNode(
|
||||
options: NodeExtensionOptions
|
||||
): NodeExtensionOptions
|
||||
|
||||
/** @deprecated Use `defineNode` instead. Will be removed in v1.0. */
|
||||
export declare function defineNodeExtension(
|
||||
options: NodeExtensionOptions
|
||||
): NodeExtensionOptions
|
||||
@@ -82,7 +87,7 @@ export declare function defineNodeExtension(
|
||||
/**
|
||||
* Register an extension for app-wide lifecycle and shell UI contributions.
|
||||
*
|
||||
* Use `defineNodeExtension` for node/widget interactions. Use this for
|
||||
* Use `defineNode` for node/widget interactions. Use this for
|
||||
* `init`, `setup`, sidebar tabs, commands, and other app-level concerns.
|
||||
*
|
||||
* @publicAPI
|
||||
@@ -109,6 +114,11 @@ export declare function defineExtension(
|
||||
* @stability experimental
|
||||
* @publicAPI
|
||||
*/
|
||||
export declare function defineWidget(
|
||||
options: WidgetExtensionOptions
|
||||
): WidgetExtensionOptions
|
||||
|
||||
/** @deprecated Use `defineWidget` instead. Will be removed in v1.0. */
|
||||
export declare function defineWidgetExtension(
|
||||
options: WidgetExtensionOptions
|
||||
): WidgetExtensionOptions
|
||||
|
||||
@@ -192,9 +192,9 @@ export interface NodeBeforeSerializeEvent {
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineNodeExtension } from '@comfyorg/extension-api'
|
||||
* import { defineNode } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineNodeExtension({
|
||||
* export default defineNode({
|
||||
* name: 'my-size-enforcer',
|
||||
* nodeTypes: ['MyCustomNode'],
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Extension option interfaces — the type contracts for `defineNodeExtension`,
|
||||
* `defineExtension`, and `defineWidgetExtension`.
|
||||
* Extension option interfaces — the type contracts for `defineNode`,
|
||||
* `defineExtension`, and `defineWidget`.
|
||||
*
|
||||
* Lives in its own module so the runtime service (`@/services/extension-api-service`)
|
||||
* and the public lifecycle barrel (`@/extension-api/lifecycle`) can both depend on
|
||||
@@ -15,14 +15,14 @@ import type { NodeHandle } from './node'
|
||||
import type { WidgetHandle } from './widget'
|
||||
|
||||
/**
|
||||
* Options for `defineNodeExtension`. Describes an extension that reacts to
|
||||
* Options for `defineNode`. Describes an extension that reacts to
|
||||
* node lifecycle events.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineNodeExtension } from '@comfyorg/extension-api'
|
||||
* import { defineNode } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineNodeExtension({
|
||||
* export default defineNode({
|
||||
* name: 'my-org.my-extension',
|
||||
* nodeTypes: ['KSampler'],
|
||||
*
|
||||
@@ -118,15 +118,15 @@ export interface ExtensionOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for `defineWidgetExtension`. Describes an extension that provides a
|
||||
* Options for `defineWidget`. Describes an extension that provides a
|
||||
* custom widget type with its own DOM rendering.
|
||||
*
|
||||
* @stability experimental
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineWidgetExtension } from '@comfyorg/extension-api'
|
||||
* import { defineWidget } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineWidgetExtension({
|
||||
* export default defineWidget({
|
||||
* name: 'my-org.color-picker',
|
||||
* type: 'COLOR_PICKER',
|
||||
*
|
||||
|
||||
@@ -232,9 +232,9 @@ export interface WidgetBeforeQueueEvent {
|
||||
* @typeParam T - The type of `getValue()` / `setValue()`. Defaults to `WidgetValue`.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { defineNodeExtension } from '@comfyorg/extension-api'
|
||||
* import { defineNode } from '@comfyorg/extension-api'
|
||||
*
|
||||
* export default defineNodeExtension({
|
||||
* export default defineNode({
|
||||
* name: 'my-extension',
|
||||
* nodeCreated(node) {
|
||||
* const steps = node.getWidget('steps')
|
||||
|
||||
@@ -860,7 +860,7 @@ export class ComfyApp {
|
||||
void useSubgraphStore().fetchSubgraphs()
|
||||
await useExtensionService().loadExtensions()
|
||||
// Start the v2 node-extension reactive mount watcher (I-SR.3 / MIG1.E5).
|
||||
// Must run after loadExtensions() so all defineNodeExtension() calls have
|
||||
// Must run after loadExtensions() so all defineNode() calls have
|
||||
// pushed into nodeExtensions[] before the first watcher tick.
|
||||
startExtensionSystem()
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ vi.mock('@/extension-api/lifecycle', () => ({}))
|
||||
// ── Import service (after mocks are in place) ────────────────────────────────
|
||||
import {
|
||||
_clearExtensionsForTesting,
|
||||
defineNodeExtension,
|
||||
defineNode,
|
||||
getCurrentScope,
|
||||
getScopeRegistry,
|
||||
mountExtensionsForNode,
|
||||
@@ -93,7 +93,7 @@ describe('scope-registry — D12 copy/paste reset semantics', () => {
|
||||
// The extension stores a ref so we can mutate it after mount.
|
||||
const counters = new Map<NodeEntityId, ReturnType<typeof ref>>()
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'z-counter',
|
||||
nodeCreated(handle) {
|
||||
const count = ref(0)
|
||||
@@ -141,7 +141,7 @@ describe('scope-registry — D12 copy/paste reset semantics', () => {
|
||||
|
||||
let setupCallCount = 0
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'a-setup-counter',
|
||||
nodeCreated() {
|
||||
setupCallCount++
|
||||
@@ -175,7 +175,7 @@ describe('scope-registry — D12 copy/paste reset semantics', () => {
|
||||
const SOURCE_ID = makeNodeId(3)
|
||||
const CLONE_ID = makeNodeId(4)
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'b-flag',
|
||||
nodeCreated() {
|
||||
return { flag: ref(true) }
|
||||
@@ -220,7 +220,7 @@ describe('currentExtension global slot (D10a) + lifecycle hooks (I-SR.2.B3 / I-S
|
||||
const NODE_ID = makeNodeId(10)
|
||||
let scopeDuringSetup: ReturnType<typeof getCurrentScope> = null
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'c-slot-check',
|
||||
nodeCreated() {
|
||||
scopeDuringSetup = getCurrentScope()
|
||||
@@ -238,7 +238,7 @@ describe('currentExtension global slot (D10a) + lifecycle hooks (I-SR.2.B3 / I-S
|
||||
it('getCurrentScope() is restored to null after setup completes', () => {
|
||||
const NODE_ID = makeNodeId(11)
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'd-slot-restore',
|
||||
nodeCreated() {
|
||||
/* no-op */
|
||||
@@ -255,7 +255,7 @@ describe('currentExtension global slot (D10a) + lifecycle hooks (I-SR.2.B3 / I-S
|
||||
const NODE_ID = makeNodeId(12)
|
||||
const removedCb = vi.fn()
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'e-on-removed',
|
||||
nodeCreated() {
|
||||
onNodeRemoved(removedCb)
|
||||
@@ -299,7 +299,7 @@ describe('I-SR.6 — scope lifecycle invariants', () => {
|
||||
const NODE_ID = makeNodeId(30)
|
||||
let setupCount = 0
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'h-once',
|
||||
nodeCreated() {
|
||||
setupCount++
|
||||
@@ -325,7 +325,7 @@ describe('I-SR.6 — scope lifecycle invariants', () => {
|
||||
const removedCb = vi.fn()
|
||||
let setupCount = 0
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'i-promotion',
|
||||
nodeCreated() {
|
||||
setupCount++
|
||||
@@ -377,7 +377,7 @@ describe('LoadedFromWorkflow tag routes to correct hook (I-SR.3)', () => {
|
||||
const created = vi.fn()
|
||||
const loaded = vi.fn()
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'f-routing',
|
||||
nodeCreated: created,
|
||||
loadedGraphNode: loaded
|
||||
@@ -401,7 +401,7 @@ describe('LoadedFromWorkflow tag routes to correct hook (I-SR.3)', () => {
|
||||
const created = vi.fn()
|
||||
const loaded = vi.fn()
|
||||
|
||||
defineNodeExtension({
|
||||
defineNode({
|
||||
name: 'g-routing',
|
||||
nodeCreated: created,
|
||||
loadedGraphNode: loaded
|
||||
|
||||
@@ -607,14 +607,20 @@ export function defineExtension(options: ExtensionOptions): void {
|
||||
appExtensions.push(options)
|
||||
}
|
||||
|
||||
export function defineNodeExtension(options: NodeExtensionOptions): void {
|
||||
export function defineNode(options: NodeExtensionOptions): void {
|
||||
nodeExtensions.push(options)
|
||||
}
|
||||
|
||||
export function defineWidgetExtension(options: WidgetExtensionOptions): void {
|
||||
export function defineWidget(options: WidgetExtensionOptions): void {
|
||||
widgetExtensions.push(options)
|
||||
}
|
||||
|
||||
/** @deprecated Use `defineNode` instead. Will be removed in v1.0. */
|
||||
export const defineNodeExtension = defineNode
|
||||
|
||||
/** @deprecated Use `defineWidget` instead. Will be removed in v1.0. */
|
||||
export const defineWidgetExtension = defineWidget
|
||||
|
||||
/** @internal Test-only: clear all registered extensions and reset state. */
|
||||
export function _clearExtensionsForTesting(): void {
|
||||
nodeExtensions.length = 0
|
||||
|
||||
@@ -220,7 +220,7 @@ export const useExtensionService = () => {
|
||||
_warnedBeforeRegisterNodeDef.add(ext.name)
|
||||
console.warn(
|
||||
`[ComfyUI] Extension "${ext.name}" uses deprecated hook "beforeRegisterNodeDef". ` +
|
||||
'Use defineNodeExtension({ nodeCreated(handle) { ... } }) with a nodeTypes filter instead. ' +
|
||||
'Use defineNode({ nodeCreated(handle) { ... } }) with a nodeTypes filter instead. ' +
|
||||
'See https://docs.comfy.org/extensions/api for the v2 API.'
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,4 +21,9 @@ export type {
|
||||
|
||||
export type { NodeExtensionOptions, ExtensionOptions } from '@/extension-api'
|
||||
|
||||
export { defineNodeExtension, defineExtension } from '@/extension-api'
|
||||
export {
|
||||
defineNode,
|
||||
defineExtension,
|
||||
// Deprecated aliases
|
||||
defineNodeExtension
|
||||
} from '@/extension-api'
|
||||
|
||||
Reference in New Issue
Block a user