fix(ext-api): add idempotency guard for v2 demo extensions per RFR-12144-1

Per workspace executive decision (option a) on F-12144-1: v1 + v2 conversions
in dynamicPrompts/imageCrop/previewAny coexist as Phase A demos following the
strangler-fig migration pattern (D6). Both register, but only one path runs
per node — guards skip v2 when v1 is already registered to prevent:

- dynamicPrompts: double processDynamicPrompt() on serialize
- previewAny: duplicate preview_markdown/preview_text/previewMode widgets
- imageCrop: redundant setSize call (idempotent but cleaner)

Guard pattern: 1-line useExtensionStore().isExtensionInstalled('<v1-name>') check
at the top of nodeCreated.

See workspace AGENTS.md rule #8 — CI failures on the ext-api stack do not
block flips during Phase A; full CI green required only at rebase point onto
PR #11939.
This commit is contained in:
Christian Byrne
2026-05-12 18:35:53 -07:00
committed by bymyself
parent d6aa562e7a
commit a337d1cfbb
2 changed files with 12 additions and 0 deletions

View File

@@ -6,12 +6,17 @@
*/
import { defineNode, type NodeHandle } from '@/extension-api'
import { useExtensionStore } from '@/stores/extensionStore'
defineNode({
name: 'Comfy.ImageCrop.V2',
nodeTypes: ['ImageCropV2'],
nodeCreated(node: NodeHandle) {
// RFR-12144-1 strangler-fig guard (D6): no-op if v1 is registered so the
// legacy path owns sizing during Phase A coexistence.
if (useExtensionStore().isExtensionInstalled('Comfy.ImageCrop')) return
const [w, h] = node.getSize()
node.setSize([Math.max(w, 300), Math.max(h, 450)])
}

View File

@@ -14,12 +14,19 @@ import {
type NodeExecutedEvent,
type WidgetValueChangeEvent
} from '@/extension-api'
import { useExtensionStore } from '@/stores/extensionStore'
defineNode({
name: 'Comfy.PreviewAny.V2',
nodeTypes: ['PreviewAny'],
nodeCreated(node: NodeHandle) {
// RFR-12144-1 strangler-fig guard (D6): v1 + v2 coexist as Phase A demos,
// but only one path runs per node. v1 adds the same three widgets via
// beforeRegisterNodeDef + onNodeCreated patching, so if v1 is registered
// we no-op to avoid duplicate widgets on the node.
if (useExtensionStore().isExtensionInstalled('Comfy.PreviewAny')) return
const markdown = node.addWidget('MARKDOWN', 'preview_markdown', '', {
hidden: true,
readonly: true,