- Added coverage reporting for Vitest with configuration in vitest.config.mjs - Updated package.json to include new scripts for JS coverage, linting, and formatting - Modified run_quality_gate.py to allow skipping ESLint and Prettier checks - Introduced .prettierrc for consistent code formatting - Created .prettierignore to exclude specific files and directories from formatting
92 lines
3.1 KiB
JavaScript
92 lines
3.1 KiB
JavaScript
/**
|
|
* 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.
|
|
*
|
|
* Third-party code can register additional adapters at any time via
|
|
* `registerAdapter()` — no existing code needs to change.
|
|
*/
|
|
|
|
/** @typedef {import("./adapters/BaseAdapter.js").NodeStreamAdapter} NodeStreamAdapter */
|
|
|
|
/** @type {NodeStreamAdapter[]} sorted by priority descending */
|
|
const _adapters = [];
|
|
|
|
/** 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, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
_dirty = false;
|
|
}
|
|
|
|
// ── Public API ────────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Register a new adapter. Duplicates (same `name`) are silently replaced.
|
|
* @param {NodeStreamAdapter} adapter
|
|
*/
|
|
export function registerAdapter(adapter) {
|
|
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) => 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) {
|
|
const idx = _adapters.findIndex((a) => a.name === name);
|
|
if (idx >= 0) {
|
|
_adapters.splice(idx, 1);
|
|
_dirty = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find the best adapter for a given node class type and its outputs.
|
|
* @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, outputs) {
|
|
_ensureSorted();
|
|
for (const adapter of _adapters) {
|
|
try {
|
|
if (adapter.canHandle(classType, outputs)) return adapter;
|
|
} catch (e) {
|
|
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() {
|
|
_ensureSorted();
|
|
return _adapters.map((a) => ({
|
|
name: a.name,
|
|
priority: a.priority ?? 0,
|
|
description: a.description ?? "",
|
|
}));
|
|
}
|