Files
malkuthro-ComfyUI-Koolook/web/sidebar/published_setups.js
T
malkuthro 3b35e6a195 feat(setups): infer setup surface from workflow groups (#222)
* feat(setups): infer setup surface from workflow groups

* fix(setups): validate inferred setup surfaces on read

* fix(setups): reject boolean setup geometry
2026-06-07 14:45:16 +02:00

82 lines
2.6 KiB
JavaScript

// SPDX-FileCopyrightText: 2025-2026 Kforge Labs <https://github.com/malkuthro/ComfyUI-Koolook>
// SPDX-License-Identifier: GPL-3.0-only
import { getWorkflowGraph as defaultGetWorkflowGraph } from "./workflows_store.js";
const PUBLISH_ROUTE = "/koolook/api/setups";
function cloneJson(value) {
return JSON.parse(JSON.stringify(value));
}
function normalizeTags(value) {
if (Array.isArray(value)) {
return value
.filter(item => typeof item === "string")
.map(item => item.trim())
.filter(Boolean);
}
if (typeof value !== "string") return [];
return value
.split(",")
.map(item => item.trim())
.filter(Boolean);
}
function sourcePath(dirPath, wfName) {
return [...dirPath, wfName].join("/");
}
function normalizeMetadata(metadata) {
return {
id: typeof metadata?.id === "string" ? metadata.id.trim() : "",
title: typeof metadata?.title === "string" ? metadata.title.trim() : "",
description: typeof metadata?.description === "string" ? metadata.description.trim() : "",
category: typeof metadata?.category === "string" ? metadata.category.trim() : "",
tags: normalizeTags(metadata?.tags),
previewImage: typeof metadata?.previewImage === "string" ? metadata.previewImage.trim() : "",
};
}
export async function publishSavedWorkflowSetup({
dirPath,
wfName,
visualGraph,
metadata,
inputContract,
outputContract,
getWorkflowGraph = defaultGetWorkflowGraph,
fetchImpl = fetch,
}) {
const path = Array.isArray(dirPath) ? dirPath : [];
const graph = (visualGraph && typeof visualGraph === "object")
? visualGraph
: getWorkflowGraph(path, wfName);
if (!graph || typeof graph !== "object") {
throw new Error("Saved workflow not found.");
}
const payload = {
visualGraph: cloneJson(graph),
metadata: normalizeMetadata(metadata || {}),
inputContract: cloneJson(inputContract || { inputs: [] }),
outputContract: cloneJson(outputContract || { outputs: [] }),
source: {
kind: "sidebar-workflow",
path: sourcePath(path, wfName),
},
};
const response = await fetchImpl(PUBLISH_ROUTE, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const body = await response.json().catch(() => ({}));
if (!response.ok || body.ok === false) {
const errors = Array.isArray(body.errors) ? body.errors : [`Publish failed (${response.status}).`];
throw new Error(errors.join("; "));
}
return body;
}