/** * NodeStreamRegistry - adapter registry for the Node Stream system. * * Each adapter declares which ComfyUI node class_types it can handle and how * to extract viewable media from the node's output. The registry resolves the * best adapter for a given node type at runtime. * * Adapters are matched in priority order (highest first). The first adapter * whose `canHandle(classType, outputs)` returns true wins. * * The registry remains available for built-in compatibility coverage and * debug inspection, but third-party adapter registration is not part of the * active selection-only Node Stream public contract. */ /** @typedef {import("./adapters/BaseAdapter.js").NodeStreamAdapter} NodeStreamAdapter */ /** @type {NodeStreamAdapter[]} sorted by priority descending */ const _adapters: any[] = []; /** Dirty flag - set when an adapter is added/removed so the sorted list is rebuilt. */ let _dirty = false; function _ensureSorted() { if (!_dirty) return; _adapters.sort((a: any, b: any) => (b.priority ?? 0) - (a.priority ?? 0)); _dirty = false; } // -- Public API ---------------------------------------------------------------- /** * Register a new adapter for internal compatibility/debug purposes. * @param {NodeStreamAdapter} adapter */ export function registerAdapter(adapter: any): void { if (!adapter?.name) { console.warn("[NodeStream] Cannot register adapter without a name"); return; } // Replace existing adapter with the same name (hot-reload friendly) const idx = _adapters.findIndex((a: any) => a.name === adapter.name); if (idx >= 0) _adapters.splice(idx, 1); _adapters.push(adapter); _dirty = true; console.debug( `[NodeStream] Adapter registered: ${adapter.name} (priority ${adapter.priority ?? 0})`, ); } /** * Remove an adapter by name. * @param {string} name */ export function unregisterAdapter(name: string): void { const idx = _adapters.findIndex((a: any) => a.name === name); if (idx >= 0) { _adapters.splice(idx, 1); _dirty = true; } } /** * Find the best adapter in the compatibility registry. * @param {string} classType ComfyUI node class_type (e.g. "SaveImage", "LayerColorCorrection") * @param {object} outputs The outputs object from onNodeOutputsUpdated for this node * @returns {NodeStreamAdapter | null} */ export function findAdapter(classType: string, outputs: any): any { _ensureSorted(); for (const adapter of _adapters) { try { if (adapter.canHandle(classType, outputs)) return adapter; } catch (e: any) { console.debug?.(`[NodeStream] adapter.canHandle error (${adapter.name})`, e); } } return null; } /** * Return a snapshot of all registered adapters (for debug / UI listing). * @returns {ReadonlyArray<{name: string, priority: number, description: string}>} */ export function listAdapters(): unknown[] { _ensureSorted(); return _adapters.map((a: any) => ({ name: a.name, priority: a.priority ?? 0, description: a.description ?? "", })); }