diff --git a/web-plugin/index.js b/web-plugin/index.js index 8b80364..3ab28ab 100644 --- a/web-plugin/index.js +++ b/web-plugin/index.js @@ -6,336 +6,433 @@ import { generateDependencyGraph } from "https://esm.sh/comfyui-json@0.1.25"; const loadingIcon = ``; function sendEventToCD(event, data) { - const message = { - type: event, - data: data, - }; - window.parent.postMessage(JSON.stringify(message), "*"); + const message = { + type: event, + data: data, + }; + window.parent.postMessage(JSON.stringify(message), "*"); } function dispatchAPIEventData(data) { - const msg = JSON.parse(data); + const msg = JSON.parse(data); - // Custom parse error - if (msg.error) { - let message = msg.error.message; - if (msg.error.details) message += ": " + msg.error.details; - for (const [nodeID, nodeError] of Object.entries(msg.node_errors)) { - message += "\n" + nodeError.class_type + ":"; - for (const errorReason of nodeError.errors) { - message += - "\n - " + errorReason.message + ": " + errorReason.details; - } + // Custom parse error + if (msg.error) { + let message = msg.error.message; + if (msg.error.details) message += ": " + msg.error.details; + for (const [nodeID, nodeError] of Object.entries(msg.node_errors)) { + message += "\n" + nodeError.class_type + ":"; + for (const errorReason of nodeError.errors) { + message += + "\n - " + + errorReason.message + + ": " + + errorReason.details; + } + } + + app.ui.dialog.show(message); + if (msg.node_errors) { + app.lastNodeErrors = msg.node_errors; + app.canvas.draw(true, true); + } } - app.ui.dialog.show(message); - if (msg.node_errors) { - app.lastNodeErrors = msg.node_errors; - app.canvas.draw(true, true); + switch (msg.event) { + case "error": + break; + case "status": + if (msg.data.sid) { + // this.clientId = msg.data.sid; + // window.name = this.clientId; // use window name so it isnt reused when duplicating tabs + // sessionStorage.setItem("clientId", this.clientId); // store in session storage so duplicate tab can load correct workflow + } + api.dispatchEvent( + new CustomEvent("status", { detail: msg.data.status }) + ); + break; + case "progress": + api.dispatchEvent( + new CustomEvent("progress", { detail: msg.data }) + ); + break; + case "executing": + api.dispatchEvent( + new CustomEvent("executing", { detail: msg.data.node }) + ); + break; + case "executed": + api.dispatchEvent( + new CustomEvent("executed", { detail: msg.data }) + ); + break; + case "execution_start": + api.dispatchEvent( + new CustomEvent("execution_start", { detail: msg.data }) + ); + break; + case "execution_error": + api.dispatchEvent( + new CustomEvent("execution_error", { detail: msg.data }) + ); + break; + case "execution_cached": + api.dispatchEvent( + new CustomEvent("execution_cached", { detail: msg.data }) + ); + break; + default: + api.dispatchEvent(new CustomEvent(msg.type, { detail: msg.data })); + // default: + // if (this.#registered.has(msg.type)) { + // } else { + // throw new Error(`Unknown message type ${msg.type}`); + // } } - } - - switch (msg.event) { - case "error": - break; - case "status": - if (msg.data.sid) { - // this.clientId = msg.data.sid; - // window.name = this.clientId; // use window name so it isnt reused when duplicating tabs - // sessionStorage.setItem("clientId", this.clientId); // store in session storage so duplicate tab can load correct workflow - } - api.dispatchEvent(new CustomEvent("status", { detail: msg.data.status })); - break; - case "progress": - api.dispatchEvent(new CustomEvent("progress", { detail: msg.data })); - break; - case "executing": - api.dispatchEvent( - new CustomEvent("executing", { detail: msg.data.node }), - ); - break; - case "executed": - api.dispatchEvent(new CustomEvent("executed", { detail: msg.data })); - break; - case "execution_start": - api.dispatchEvent( - new CustomEvent("execution_start", { detail: msg.data }), - ); - break; - case "execution_error": - api.dispatchEvent( - new CustomEvent("execution_error", { detail: msg.data }), - ); - break; - case "execution_cached": - api.dispatchEvent( - new CustomEvent("execution_cached", { detail: msg.data }), - ); - break; - default: - api.dispatchEvent(new CustomEvent(msg.type, { detail: msg.data })); - // default: - // if (this.#registered.has(msg.type)) { - // } else { - // throw new Error(`Unknown message type ${msg.type}`); - // } - } } /** @typedef {import('../../../web/types/comfy.js').ComfyExtension} ComfyExtension*/ /** @type {ComfyExtension} */ const ext = { - name: "BennyKok.ComfyUIDeploy", + name: "BennyKok.ComfyUIDeploy", - init(app) { - addButton(); + init(app) { + addButton(); - const queryParams = new URLSearchParams(window.location.search); - const workflow_version_id = queryParams.get("workflow_version_id"); - const auth_token = queryParams.get("auth_token"); - const org_display = queryParams.get("org_display"); - const origin = queryParams.get("origin"); - const workspace_mode = queryParams.get("workspace_mode"); + const queryParams = new URLSearchParams(window.location.search); + const workflow_version_id = queryParams.get("workflow_version_id"); + const auth_token = queryParams.get("auth_token"); + const org_display = queryParams.get("org_display"); + const origin = queryParams.get("origin"); + const workspace_mode = queryParams.get("workspace_mode"); - if (workspace_mode) { - document.querySelector(".comfy-menu").style.display = "none"; + if (workspace_mode) { + document.querySelector(".comfy-menu").style.display = "none"; - sendEventToCD("cd_plugin_onInit"); + sendEventToCD("cd_plugin_onInit"); - app.queuePrompt = ((originalFunction) => async () => { - // const prompt = await app.graphToPrompt(); - sendEventToCD("cd_plugin_onQueuePromptTrigger"); - })(app.queuePrompt); + app.queuePrompt = ((originalFunction) => async () => { + // const prompt = await app.graphToPrompt(); + sendEventToCD("cd_plugin_onQueuePromptTrigger"); + })(app.queuePrompt); - // // Intercept the onkeydown event - // window.addEventListener( - // "keydown", - // (event) => { - // // Check for specific keys if necessary - // console.log("hi"); - // if ((event.metaKey || event.ctrlKey) && event.key === "Enter") { - // event.preventDefault(); - // event.stopImmediatePropagation(); - // event.stopPropagation(); - // sendEventToCD("cd_plugin_onQueuePrompt", prompt); - // } - // }, - // true, - // ); - } + // // Intercept the onkeydown event + // window.addEventListener( + // "keydown", + // (event) => { + // // Check for specific keys if necessary + // console.log("hi"); + // if ((event.metaKey || event.ctrlKey) && event.key === "Enter") { + // event.preventDefault(); + // event.stopImmediatePropagation(); + // event.stopPropagation(); + // sendEventToCD("cd_plugin_onQueuePrompt", prompt); + // } + // }, + // true, + // ); + } - const data = getData(); - let endpoint = data.endpoint; - let apiKey = data.apiKey; + const data = getData(); + let endpoint = data.endpoint; + let apiKey = data.apiKey; - // If there is auth token override it - if (auth_token) { - apiKey = auth_token; - endpoint = origin; - saveData({ - displayName: org_display, - endpoint: origin, - apiKey: auth_token, - displayName: org_display, - environment: "cloud", - }); - localStorage.setItem("comfy_deploy_env", "cloud"); - } + // If there is auth token override it + if (auth_token) { + apiKey = auth_token; + endpoint = origin; + saveData({ + displayName: org_display, + endpoint: origin, + apiKey: auth_token, + displayName: org_display, + environment: "cloud", + }); + localStorage.setItem("comfy_deploy_env", "cloud"); + } - if (!workflow_version_id) { - console.error("No workflow_version_id provided in query parameters."); - } else { - loadingDialog.showLoading( - "Loading workflow from " + org_display, - "Please wait...", - ); - fetch(endpoint + "/api/workflow-version/" + workflow_version_id, { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + apiKey, - }, - }) - .then(async (res) => { - const data = await res.json(); - const { workflow, workflow_id, error } = data; - if (error) { - infoDialog.showMessage("Unable to load this workflow", error); - return; - } + if (!workflow_version_id) { + console.error( + "No workflow_version_id provided in query parameters." + ); + } else { + loadingDialog.showLoading( + "Loading workflow from " + org_display, + "Please wait..." + ); + fetch(endpoint + "/api/workflow-version/" + workflow_version_id, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + apiKey, + }, + }) + .then(async (res) => { + const data = await res.json(); + const { workflow, workflow_id, error } = data; + if (error) { + infoDialog.showMessage( + "Unable to load this workflow", + error + ); + return; + } - // // Adding a delay to wait for the intial graph to load - // await new Promise((resolve) => setTimeout(resolve, 2000)); + // // Adding a delay to wait for the intial graph to load + // await new Promise((resolve) => setTimeout(resolve, 2000)); - workflow?.nodes.forEach((x) => { - if (x?.type === "ComfyDeploy") { - x.widgets_values[1] = workflow_id; - // x.widgets_values[2] = workflow_version.version; + workflow?.nodes.forEach((x) => { + if (x?.type === "ComfyDeploy") { + x.widgets_values[1] = workflow_id; + // x.widgets_values[2] = workflow_version.version; + } + }); + + /** @type {LGraph} */ + app.loadGraphData(workflow); + }) + .catch((e) => infoDialog.showMessage("Error", e.message)) + .finally(() => { + loadingDialog.close(); + window.history.replaceState( + {}, + document.title, + window.location.pathname + ); + }); + } + }, + + registerCustomNodes() { + /** @type {LGraphNode}*/ + class ComfyDeploy { + color = LGraphCanvas.node_colors.yellow.color; + bgcolor = LGraphCanvas.node_colors.yellow.bgcolor; + groupcolor = LGraphCanvas.node_colors.yellow.groupcolor; + constructor() { + if (!this.properties) { + this.properties = {}; + this.properties.workflow_name = ""; + this.properties.workflow_id = ""; + this.properties.version = ""; + } + + ComfyWidgets.STRING( + this, + "workflow_name", + [ + "", + { + default: this.properties.workflow_name, + multiline: false, + }, + ], + app + ); + + ComfyWidgets.STRING( + this, + "workflow_id", + [ + "", + { + default: this.properties.workflow_id, + multiline: false, + }, + ], + app + ); + + ComfyWidgets.STRING( + this, + "version", + [ + "", + { default: this.properties.version, multiline: false }, + ], + app + ); + + // this.widgets.forEach((w) => { + // // w.computeSize = () => [200,10] + // w.computedHeight = 2; + // }) + + this.widgets_start_y = 10; + this.setSize(this.computeSize()); + + // const config = { }; + + // console.log(this); + this.serialize_widgets = true; + this.isVirtualNode = true; } - }); + } - /** @type {LGraph} */ - app.loadGraphData(workflow); - }) - .catch((e) => infoDialog.showMessage("Error", e.message)) - .finally(() => { - loadingDialog.close(); - window.history.replaceState( - {}, - document.title, - window.location.pathname, - ); + // Load default visibility + + LiteGraph.registerNodeType( + "ComfyDeploy", + Object.assign(ComfyDeploy, { + title_mode: LiteGraph.NORMAL_TITLE, + title: "Comfy Deploy", + collapsable: true, + }) + ); + + ComfyDeploy.category = "deploy"; + }, + + async setup() { + // const graphCanvas = document.getElementById("graph-canvas"); + + window.addEventListener("message", async (event) => { + // console.log("message", event); + try { + const message = JSON.parse(event.data); + if (message.type === "graph_load") { + const comfyUIWorkflow = message.data; + // console.log("recieved: ", comfyUIWorkflow); + // Assuming there's a method to load the workflow data into the ComfyUI + // This part of the code would depend on how the ComfyUI expects to receive and process the workflow data + // For demonstration, let's assume there's a loadWorkflow method in the ComfyUI API + if (comfyUIWorkflow && app && app.loadGraphData) { + console.log("loadGraphData"); + app.loadGraphData(comfyUIWorkflow); + } + } else if (message.type === "deploy") { + // deployWorkflow(); + const prompt = await app.graphToPrompt(); + // api.handlePromptGenerated(prompt); + sendEventToCD("cd_plugin_onDeployChanges", prompt); + } else if (message.type === "queue_prompt") { + const prompt = await app.graphToPrompt(); + if (typeof api.handlePromptGenerated === "function") { + api.handlePromptGenerated(prompt); + } else { + console.warn( + "api.handlePromptGenerated is not a function" + ); + } + sendEventToCD("cd_plugin_onQueuePrompt", prompt); + } else if (message.type === "get_prompt") { + const prompt = await app.graphToPrompt(); + sendEventToCD("cd_plugin_onGetPrompt", prompt); + } else if (message.type === "event") { + dispatchAPIEventData(message.data); + } else if (message.type === "add_node") { + console.log("add node", message.data); + app.graph.beforeChange(); + var node = LiteGraph.createNode(message.data.type); + node.configure({ + widgets_values: message.data.widgets_values, + }); + + console.log("node", node); + + const graphMouse = app.canvas.graph_mouse; + + node.pos = [graphMouse[0], graphMouse[1]]; + + app.graph.add(node); + app.graph.afterChange(); + } else if (message.type === "zoom_to_node") { + const nodeId = message.data.nodeId; + const position = message.data.position; + + const node = app.graph.getNodeById(nodeId); + if (!node) return; + + const canvas = app.canvas; + const targetScale = 1; + const targetOffsetX = + canvas.canvas.width / 4 - + position[0] - + node.size[0] / 2; + const targetOffsetY = + canvas.canvas.height / 4 - + position[1] - + node.size[1] / 2; + + const startScale = canvas.ds.scale; + const startOffsetX = canvas.ds.offset[0]; + const startOffsetY = canvas.ds.offset[1]; + + const duration = 400; // Animation duration in milliseconds + const startTime = Date.now(); + + function easeOutCubic(t) { + return 1 - Math.pow(1 - t, 3); + } + + function lerp(start, end, t) { + return start * (1 - t) + end * t; + } + + function animate() { + const currentTime = Date.now(); + const elapsedTime = currentTime - startTime; + const t = Math.min(elapsedTime / duration, 1); + + const easedT = easeOutCubic(t); + + const currentScale = lerp( + startScale, + targetScale, + easedT + ); + const currentOffsetX = lerp( + startOffsetX, + targetOffsetX, + easedT + ); + const currentOffsetY = lerp( + startOffsetY, + targetOffsetY, + easedT + ); + + canvas.setZoom(currentScale); + canvas.ds.offset = [currentOffsetX, currentOffsetY]; + canvas.draw(true, true); + + if (t < 1) { + requestAnimationFrame(animate); + } + } + + animate(); + } + // else if (message.type === "refresh") { + // sendEventToCD("cd_plugin_onRefresh"); + // } + } catch (error) { + // console.error("Error processing message:", error); + } }); - } - }, - registerCustomNodes() { - /** @type {LGraphNode}*/ - class ComfyDeploy { - color = LGraphCanvas.node_colors.yellow.color; - bgcolor = LGraphCanvas.node_colors.yellow.bgcolor; - groupcolor = LGraphCanvas.node_colors.yellow.groupcolor; - constructor() { - if (!this.properties) { - this.properties = {}; - this.properties.workflow_name = ""; - this.properties.workflow_id = ""; - this.properties.version = ""; - } + api.addEventListener("executed", (evt) => { + const images = evt.detail?.output.images; + // if (images?.length > 0 && images[0].type === "output") { + // generatedImages[evt.detail.node] = images[0].filename; + // } + // if (evt.detail?.output.gltfFilename) { - ComfyWidgets.STRING( - this, - "workflow_name", - ["", { default: this.properties.workflow_name, multiline: false }], - app, - ); + // } + }); - ComfyWidgets.STRING( - this, - "workflow_id", - ["", { default: this.properties.workflow_id, multiline: false }], - app, - ); + app.graph.onAfterChange = ((originalFunction) => + async function () { + const prompt = await app.graphToPrompt(); + sendEventToCD("cd_plugin_onAfterChange", prompt); - ComfyWidgets.STRING( - this, - "version", - ["", { default: this.properties.version, multiline: false }], - app, - ); + if (typeof originalFunction === "function") { + originalFunction.apply(this, arguments); + } + })(app.graph.onAfterChange); - // this.widgets.forEach((w) => { - // // w.computeSize = () => [200,10] - // w.computedHeight = 2; - // }) - - this.widgets_start_y = 10; - this.setSize(this.computeSize()); - - // const config = { }; - - // console.log(this); - this.serialize_widgets = true; - this.isVirtualNode = true; - } - } - - // Load default visibility - - LiteGraph.registerNodeType( - "ComfyDeploy", - Object.assign(ComfyDeploy, { - title_mode: LiteGraph.NORMAL_TITLE, - title: "Comfy Deploy", - collapsable: true, - }), - ); - - ComfyDeploy.category = "deploy"; - }, - - async setup() { - // const graphCanvas = document.getElementById("graph-canvas"); - - window.addEventListener("message", async (event) => { - // console.log("message", event); - try { - const message = JSON.parse(event.data); - if (message.type === "graph_load") { - const comfyUIWorkflow = message.data; - // console.log("recieved: ", comfyUIWorkflow); - // Assuming there's a method to load the workflow data into the ComfyUI - // This part of the code would depend on how the ComfyUI expects to receive and process the workflow data - // For demonstration, let's assume there's a loadWorkflow method in the ComfyUI API - if (comfyUIWorkflow && app && app.loadGraphData) { - console.log("loadGraphData"); - app.loadGraphData(comfyUIWorkflow); - } - } else if (message.type === "deploy") { - // deployWorkflow(); - const prompt = await app.graphToPrompt(); - // api.handlePromptGenerated(prompt); - sendEventToCD("cd_plugin_onDeployChanges", prompt); - } else if (message.type === "queue_prompt") { - const prompt = await app.graphToPrompt(); - if (typeof api.handlePromptGenerated === "function") { - api.handlePromptGenerated(prompt); - } else { - console.warn("api.handlePromptGenerated is not a function"); - } - sendEventToCD("cd_plugin_onQueuePrompt", prompt); - } else if (message.type === "get_prompt") { - const prompt = await app.graphToPrompt(); - sendEventToCD("cd_plugin_onGetPrompt", prompt); - } else if (message.type === "event") { - dispatchAPIEventData(message.data); - } else if (message.type === "add_node") { - console.log("add node", message.data); - app.graph.beforeChange(); - var node = LiteGraph.createNode(message.data.type); - node.configure({ - widgets_values: message.data.widgets_values, - }); - - console.log("node", node); - - const graphMouse = app.canvas.graph_mouse; - - node.pos = [graphMouse[0], graphMouse[1]]; - - app.graph.add(node); - app.graph.afterChange(); - } - // else if (message.type === "refresh") { - // sendEventToCD("cd_plugin_onRefresh"); - // } - } catch (error) { - // console.error("Error processing message:", error); - } - }); - - api.addEventListener("executed", (evt) => { - const images = evt.detail?.output.images; - // if (images?.length > 0 && images[0].type === "output") { - // generatedImages[evt.detail.node] = images[0].filename; - // } - // if (evt.detail?.output.gltfFilename) { - - // } - }); - - app.graph.onAfterChange = ((originalFunction) => - async function () { - const prompt = await app.graphToPrompt(); - sendEventToCD("cd_plugin_onAfterChange", prompt); - - if (typeof originalFunction === "function") { - originalFunction.apply(this, arguments); - } - })(app.graph.onAfterChange); - - sendEventToCD("cd_plugin_setup"); - }, + sendEventToCD("cd_plugin_setup"); + }, }; /** @@ -344,133 +441,138 @@ const ext = { */ function showError(title, message) { - infoDialog.show( - `

${title}


${message} `, - ); + infoDialog.show( + `

${title}


${message} ` + ); } function createDynamicUIHtml(data) { - console.log(data); - let html = - '
'; - const bgcolor = "var(--comfy-input-bg)"; - const evenBg = "var(--border-color)"; - const textColor = "var(--input-text)"; + console.log(data); + let html = + '
'; + const bgcolor = "var(--comfy-input-bg)"; + const evenBg = "var(--border-color)"; + const textColor = "var(--input-text)"; - // Custom Nodes - html += `
`; - html += - '

Custom Nodes

'; + // Custom Nodes + html += `
`; + html += + '

Custom Nodes

'; - if (data.missing_nodes?.length > 0) { - html += ` + if (data.missing_nodes?.length > 0) { + html += `

Missing Nodes

These nodes are not found with any matching custom_nodes in the ComfyUI Manager Database

${data.missing_nodes - .map((node) => { - return `

${node}

`; - }) - .join("")} + .map((node) => { + return `

${node}

`; + }) + .join("")}
`; - } + } - Object.values(data.custom_nodes).forEach((node) => { - html += ` + Object.values(data.custom_nodes).forEach((node) => { + html += `
- ${node.name - } + ${ + node.name + }

${node.hash}

- ${node.warning - ? `

${node.warning}

` - : "" - } + ${ + node.warning + ? `

${node.warning}

` + : "" + }
`; - }); - html += "
"; - - // Models - html += `
`; - html += - '

Models

'; - - Object.entries(data.models).forEach(([section, items]) => { - html += ` -
-

${section.charAt(0).toUpperCase() + section.slice(1) - }

`; - items.forEach((item) => { - html += `

${item.name}

`; }); html += "
"; - }); - html += "
"; - // Models - html += `
`; - html += - '

Files

'; + // Models + html += `
`; + html += + '

Models

'; - Object.entries(data.files).forEach(([section, items]) => { - html += ` + Object.entries(data.models).forEach(([section, items]) => { + html += `
-

${section.charAt(0).toUpperCase() + section.slice(1) - }

`; - items.forEach((item) => { - html += `

${item.name}

`; +

${ + section.charAt(0).toUpperCase() + section.slice(1) + }

`; + items.forEach((item) => { + html += `

${item.name}

`; + }); + html += "
"; }); html += "
"; - }); - html += "
"; - html += "
"; - return html; + // Models + html += `
`; + html += + '

Files

'; + + Object.entries(data.files).forEach(([section, items]) => { + html += ` +
+

${ + section.charAt(0).toUpperCase() + section.slice(1) + }

`; + items.forEach((item) => { + html += `

${item.name}

`; + }); + html += "
"; + }); + html += "
"; + + html += "
"; + return html; } async function deployWorkflow() { - const deploy = document.getElementById("deploy-button"); + const deploy = document.getElementById("deploy-button"); - /** @type {LGraph} */ - const graph = app.graph; + /** @type {LGraph} */ + const graph = app.graph; - let { endpoint, apiKey, displayName } = getData(); + let { endpoint, apiKey, displayName } = getData(); - if (!endpoint || !apiKey || apiKey === "" || endpoint === "") { - configDialog.show(); - return; - } + if (!endpoint || !apiKey || apiKey === "" || endpoint === "") { + configDialog.show(); + return; + } - let deployMeta = graph.findNodesByType("ComfyDeploy"); + let deployMeta = graph.findNodesByType("ComfyDeploy"); - if (deployMeta.length == 0) { - const text = await inputDialog.input( - "Create your deployment", - "Workflow name", - ); - if (!text) return; - console.log(text); - app.graph.beforeChange(); - var node = LiteGraph.createNode("ComfyDeploy"); - node.configure({ - widgets_values: [text], - }); - node.pos = [0, 0]; - app.graph.add(node); - app.graph.afterChange(); - deployMeta = [node]; - } + if (deployMeta.length == 0) { + const text = await inputDialog.input( + "Create your deployment", + "Workflow name" + ); + if (!text) return; + console.log(text); + app.graph.beforeChange(); + var node = LiteGraph.createNode("ComfyDeploy"); + node.configure({ + widgets_values: [text], + }); + node.pos = [0, 0]; + app.graph.add(node); + app.graph.afterChange(); + deployMeta = [node]; + } - const deployMetaNode = deployMeta[0]; + const deployMetaNode = deployMeta[0]; - const workflow_name = deployMetaNode.widgets[0].value; - const workflow_id = deployMetaNode.widgets[1].value; + const workflow_name = deployMetaNode.widgets[0].value; + const workflow_id = deployMetaNode.widgets[1].value; - const ok = await confirmDialog.confirm( - `Confirm deployment`, - ` + const ok = await confirmDialog.confirm( + `Confirm deployment`, + `
A new version of will be deployed, do you confirm? @@ -489,261 +591,269 @@ async function deployWorkflow() { Reuse hash from last version
- `, - ); - if (!ok) return; - - const includeDeps = document.getElementById("include-deps").checked; - const reuseHash = document.getElementById("reuse-hash").checked; - - if (endpoint.endsWith("/")) { - endpoint = endpoint.slice(0, -1); - } - loadingDialog.showLoading("Generating snapshot"); - - const snapshot = await fetch("/snapshot/get_current").then((x) => x.json()); - // console.log(snapshot); - loadingDialog.close(); - - if (!snapshot) { - showError( - "Error when deploying", - "Unable to generate snapshot, please install ComfyUI Manager", + ` ); - return; - } + if (!ok) return; - const title = deploy.querySelector("#button-title"); + const includeDeps = document.getElementById("include-deps").checked; + const reuseHash = document.getElementById("reuse-hash").checked; - const prompt = await app.graphToPrompt(); - let deps = undefined; - - if (includeDeps) { - loadingDialog.showLoading("Fetching existing version"); - - const existing_workflow = await fetch( - endpoint + "/api/workflow/" + workflow_id, - { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: "Bearer " + apiKey, - }, - }, - ) - .then((x) => x.json()) - .catch(() => { - return {}; - }); + if (endpoint.endsWith("/")) { + endpoint = endpoint.slice(0, -1); + } + loadingDialog.showLoading("Generating snapshot"); + const snapshot = await fetch("/snapshot/get_current").then((x) => x.json()); + // console.log(snapshot); loadingDialog.close(); - loadingDialog.showLoading("Generating dependency graph"); - deps = await generateDependencyGraph({ - workflow_api: prompt.output, - snapshot: snapshot, - computeFileHash: async (file) => { - console.log(existing_workflow?.dependencies?.models); + if (!snapshot) { + showError( + "Error when deploying", + "Unable to generate snapshot, please install ComfyUI Manager" + ); + return; + } - // Match previous hash for models - if (reuseHash && existing_workflow?.dependencies?.models) { - const previousModelHash = Object.entries( - existing_workflow?.dependencies?.models, - ).flatMap(([key, value]) => { - return Object.values(value).map((x) => ({ - ...x, - name: "models/" + key + "/" + x.name, - })); - }); - console.log(previousModelHash); + const title = deploy.querySelector("#button-title"); - const match = previousModelHash.find((x) => { - console.log(file, x.name); - return file == x.name; - }); - console.log(match); - if (match && match.hash) { - console.log("cached hash used"); - return match.hash; - } - } - console.log(file); - loadingDialog.showLoading("Generating hash", file); - const hash = await fetch( - `/comfyui-deploy/get-file-hash?file_path=${encodeURIComponent(file)}`, - ).then((x) => x.json()); - loadingDialog.showLoading("Generating hash", file); - console.log(hash); - return hash.file_hash; - }, - handleFileUpload: async (file, hash, prevhash) => { - console.log("Uploading ", file); - loadingDialog.showLoading("Uploading file", file); - try { - const { download_url } = await fetch(`/comfyui-deploy/upload-file`, { - method: "POST", - body: JSON.stringify({ - file_path: file, - token: apiKey, - url: endpoint + "/api/upload-url", - }), - }) + const prompt = await app.graphToPrompt(); + let deps = undefined; + + if (includeDeps) { + loadingDialog.showLoading("Fetching existing version"); + + const existing_workflow = await fetch( + endpoint + "/api/workflow/" + workflow_id, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + apiKey, + }, + } + ) .then((x) => x.json()) .catch(() => { - loadingDialog.close(); - confirmDialog.confirm("Error", "Unable to upload file " + file); + return {}; }); - loadingDialog.showLoading("Uploaded file", file); - console.log(download_url); - return download_url; - } catch (error) { - return undefined; - } - }, - existingDependencies: existing_workflow.dependencies, - }); - // Need to find a way to include this if this is not included in comfyui-json level - if ( - !deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy"] && - !deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy.git"] - ) - deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy"] = { - url: "https://github.com/BennyKok/comfyui-deploy", - install_type: "git-clone", - hash: - snapshot?.git_custom_nodes?.[ - "https://github.com/BennyKok/comfyui-deploy" - ]?.hash ?? "HEAD", - name: "ComfyUI Deploy", - }; + loadingDialog.close(); - loadingDialog.close(); + loadingDialog.showLoading("Generating dependency graph"); + deps = await generateDependencyGraph({ + workflow_api: prompt.output, + snapshot: snapshot, + computeFileHash: async (file) => { + console.log(existing_workflow?.dependencies?.models); - const depsOk = await confirmDialog.confirm( - "Check dependencies", - // JSON.stringify(deps, null, 2), - ` + // Match previous hash for models + if (reuseHash && existing_workflow?.dependencies?.models) { + const previousModelHash = Object.entries( + existing_workflow?.dependencies?.models + ).flatMap(([key, value]) => { + return Object.values(value).map((x) => ({ + ...x, + name: "models/" + key + "/" + x.name, + })); + }); + console.log(previousModelHash); + + const match = previousModelHash.find((x) => { + console.log(file, x.name); + return file == x.name; + }); + console.log(match); + if (match && match.hash) { + console.log("cached hash used"); + return match.hash; + } + } + console.log(file); + loadingDialog.showLoading("Generating hash", file); + const hash = await fetch( + `/comfyui-deploy/get-file-hash?file_path=${encodeURIComponent( + file + )}` + ).then((x) => x.json()); + loadingDialog.showLoading("Generating hash", file); + console.log(hash); + return hash.file_hash; + }, + handleFileUpload: async (file, hash, prevhash) => { + console.log("Uploading ", file); + loadingDialog.showLoading("Uploading file", file); + try { + const { download_url } = await fetch( + `/comfyui-deploy/upload-file`, + { + method: "POST", + body: JSON.stringify({ + file_path: file, + token: apiKey, + url: endpoint + "/api/upload-url", + }), + } + ) + .then((x) => x.json()) + .catch(() => { + loadingDialog.close(); + confirmDialog.confirm( + "Error", + "Unable to upload file " + file + ); + }); + loadingDialog.showLoading("Uploaded file", file); + console.log(download_url); + return download_url; + } catch (error) { + return undefined; + } + }, + existingDependencies: existing_workflow.dependencies, + }); + + // Need to find a way to include this if this is not included in comfyui-json level + if ( + !deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy"] && + !deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy.git"] + ) + deps.custom_nodes["https://github.com/BennyKok/comfyui-deploy"] = { + url: "https://github.com/BennyKok/comfyui-deploy", + install_type: "git-clone", + hash: + snapshot?.git_custom_nodes?.[ + "https://github.com/BennyKok/comfyui-deploy" + ]?.hash ?? "HEAD", + name: "ComfyUI Deploy", + }; + + loadingDialog.close(); + + const depsOk = await confirmDialog.confirm( + "Check dependencies", + // JSON.stringify(deps, null, 2), + `
${loadingIcon}