mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-03 06:47:33 +00:00
Add more Zod types to api.ts (#440)
This commit is contained in:
@@ -4,7 +4,13 @@ import {
|
||||
PendingTaskItem,
|
||||
RunningTaskItem,
|
||||
ComfyNodeDef,
|
||||
validateComfyNodeDef
|
||||
validateComfyNodeDef,
|
||||
EmbeddingsResponse,
|
||||
ExtensionsResponse,
|
||||
PromptResponse,
|
||||
SystemStats,
|
||||
User,
|
||||
Settings
|
||||
} from '@/types/apiTypes'
|
||||
|
||||
interface QueuePromptRequestBody {
|
||||
@@ -47,7 +53,7 @@ class ComfyApi extends EventTarget {
|
||||
return this.api_base + route
|
||||
}
|
||||
|
||||
fetchApi(route, options?) {
|
||||
fetchApi(route: string, options?: RequestInit) {
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
@@ -55,13 +61,17 @@ class ComfyApi extends EventTarget {
|
||||
options.headers = {}
|
||||
}
|
||||
if (!options.cache) {
|
||||
options.cache = 'no-cache'
|
||||
options.cache = 'no-cache'
|
||||
}
|
||||
options.headers['Comfy-User'] = this.user
|
||||
return fetch(this.apiURL(route), options)
|
||||
}
|
||||
|
||||
addEventListener(type, callback, options?) {
|
||||
addEventListener(
|
||||
type: string,
|
||||
callback: any,
|
||||
options?: AddEventListenerOptions
|
||||
) {
|
||||
super.addEventListener(type, callback, options)
|
||||
this.#registered.add(type)
|
||||
}
|
||||
@@ -85,7 +95,7 @@ class ComfyApi extends EventTarget {
|
||||
* Creates and connects a WebSocket for realtime updates
|
||||
* @param {boolean} isReconnect If the socket is connection is a reconnect attempt
|
||||
*/
|
||||
#createSocket(isReconnect?) {
|
||||
#createSocket(isReconnect?: boolean) {
|
||||
if (this.socket) {
|
||||
return
|
||||
}
|
||||
@@ -232,18 +242,16 @@ class ComfyApi extends EventTarget {
|
||||
|
||||
/**
|
||||
* Gets a list of extension urls
|
||||
* @returns An array of script urls to import
|
||||
*/
|
||||
async getExtensions() {
|
||||
async getExtensions(): Promise<ExtensionsResponse> {
|
||||
const resp = await this.fetchApi('/extensions', { cache: 'no-store' })
|
||||
return await resp.json()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of embedding names
|
||||
* @returns An array of script urls to import
|
||||
*/
|
||||
async getEmbeddings() {
|
||||
async getEmbeddings(): Promise<EmbeddingsResponse> {
|
||||
const resp = await this.fetchApi('/embeddings', { cache: 'no-store' })
|
||||
return await resp.json()
|
||||
}
|
||||
@@ -278,7 +286,10 @@ class ComfyApi extends EventTarget {
|
||||
* @param {number} number The index at which to queue the prompt, passing -1 will insert the prompt at the front of the queue
|
||||
* @param {object} prompt The prompt data to queue
|
||||
*/
|
||||
async queuePrompt(number: number, { output, workflow }) {
|
||||
async queuePrompt(
|
||||
number: number,
|
||||
{ output, workflow }
|
||||
): Promise<PromptResponse> {
|
||||
const body: QueuePromptRequestBody = {
|
||||
client_id: this.clientId,
|
||||
prompt: output,
|
||||
@@ -313,7 +324,7 @@ class ComfyApi extends EventTarget {
|
||||
* @param {string} type The type of items to load, queue or history
|
||||
* @returns The items of the specified type grouped by their status
|
||||
*/
|
||||
async getItems(type) {
|
||||
async getItems(type: 'queue' | 'history') {
|
||||
if (type === 'queue') {
|
||||
return this.getQueue()
|
||||
}
|
||||
@@ -358,10 +369,12 @@ class ComfyApi extends EventTarget {
|
||||
): Promise<{ History: HistoryTaskItem[] }> {
|
||||
try {
|
||||
const res = await this.fetchApi(`/history?max_items=${max_items}`)
|
||||
const json: Promise<HistoryTaskItem[]> = await res.json()
|
||||
return {
|
||||
History: Object.values(await res.json()).map(
|
||||
(item: HistoryTaskItem) => ({ ...item, taskType: 'History' })
|
||||
)
|
||||
History: Object.values(json).map((item) => ({
|
||||
...item,
|
||||
taskType: 'History'
|
||||
}))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
@@ -373,7 +386,7 @@ class ComfyApi extends EventTarget {
|
||||
* Gets system & device stats
|
||||
* @returns System stats such as python version, OS, per device info
|
||||
*/
|
||||
async getSystemStats() {
|
||||
async getSystemStats(): Promise<SystemStats> {
|
||||
const res = await this.fetchApi('/system_stats')
|
||||
return await res.json()
|
||||
}
|
||||
@@ -383,7 +396,7 @@ class ComfyApi extends EventTarget {
|
||||
* @param {*} type The endpoint to post to
|
||||
* @param {*} body Optional POST data
|
||||
*/
|
||||
async #postItem(type, body) {
|
||||
async #postItem(type: string, body: any) {
|
||||
try {
|
||||
await this.fetchApi('/' + type, {
|
||||
method: 'POST',
|
||||
@@ -402,7 +415,7 @@ class ComfyApi extends EventTarget {
|
||||
* @param {string} type The type of item to delete, queue or history
|
||||
* @param {number} id The id of the item to delete
|
||||
*/
|
||||
async deleteItem(type, id) {
|
||||
async deleteItem(type: string, id: string) {
|
||||
await this.#postItem(type, { delete: [id] })
|
||||
}
|
||||
|
||||
@@ -410,7 +423,7 @@ class ComfyApi extends EventTarget {
|
||||
* Clears the specified list
|
||||
* @param {string} type The type of list to clear, queue or history
|
||||
*/
|
||||
async clearItems(type) {
|
||||
async clearItems(type: string) {
|
||||
await this.#postItem(type, { clear: true })
|
||||
}
|
||||
|
||||
@@ -423,9 +436,8 @@ class ComfyApi extends EventTarget {
|
||||
|
||||
/**
|
||||
* Gets user configuration data and where data should be stored
|
||||
* @returns { Promise<{ storage: "server" | "browser", users?: Promise<string, unknown>, migrated?: boolean }> }
|
||||
*/
|
||||
async getUserConfig() {
|
||||
async getUserConfig(): Promise<User> {
|
||||
return (await this.fetchApi('/users')).json()
|
||||
}
|
||||
|
||||
@@ -434,7 +446,7 @@ class ComfyApi extends EventTarget {
|
||||
* @param { string } username
|
||||
* @returns The fetch response
|
||||
*/
|
||||
createUser(username) {
|
||||
createUser(username: string) {
|
||||
return this.fetchApi('/users', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -448,7 +460,7 @@ class ComfyApi extends EventTarget {
|
||||
* Gets all setting values for the current user
|
||||
* @returns { Promise<string, unknown> } A dictionary of id -> value
|
||||
*/
|
||||
async getSettings() {
|
||||
async getSettings(): Promise<Settings> {
|
||||
return (await this.fetchApi('/settings')).json()
|
||||
}
|
||||
|
||||
@@ -457,16 +469,14 @@ class ComfyApi extends EventTarget {
|
||||
* @param { string } id The id of the setting to fetch
|
||||
* @returns { Promise<unknown> } The setting value
|
||||
*/
|
||||
async getSetting(id) {
|
||||
async getSetting(id: keyof Settings): Promise<Settings[keyof Settings]> {
|
||||
return (await this.fetchApi(`/settings/${encodeURIComponent(id)}`)).json()
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a dictionary of settings for the current user
|
||||
* @param { Record<string, unknown> } settings Dictionary of setting id -> value to save
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
async storeSettings(settings) {
|
||||
async storeSettings(settings: Settings) {
|
||||
return this.fetchApi(`/settings`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(settings)
|
||||
@@ -475,11 +485,8 @@ class ComfyApi extends EventTarget {
|
||||
|
||||
/**
|
||||
* Stores a setting for the current user
|
||||
* @param { string } id The id of the setting to update
|
||||
* @param { unknown } value The value of the setting
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
async storeSetting(id, value) {
|
||||
async storeSetting(id: keyof Settings, value: Settings[keyof Settings]) {
|
||||
return this.fetchApi(`/settings/${encodeURIComponent(id)}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(value)
|
||||
@@ -488,11 +495,8 @@ class ComfyApi extends EventTarget {
|
||||
|
||||
/**
|
||||
* Gets a user data file for the current user
|
||||
* @param { string } file The name of the userdata file to load
|
||||
* @param { RequestInit } [options]
|
||||
* @returns { Promise<unknown> } The fetch response object
|
||||
*/
|
||||
async getUserData(file, options?) {
|
||||
async getUserData(file: string, options?: RequestInit) {
|
||||
return this.fetchApi(`/userdata/${encodeURIComponent(file)}`, options)
|
||||
}
|
||||
|
||||
@@ -505,7 +509,7 @@ class ComfyApi extends EventTarget {
|
||||
*/
|
||||
async storeUserData(
|
||||
file: string,
|
||||
data: unknown,
|
||||
data: any,
|
||||
options: RequestInit & {
|
||||
overwrite?: boolean
|
||||
stringify?: boolean
|
||||
@@ -533,7 +537,7 @@ class ComfyApi extends EventTarget {
|
||||
* Deletes a user data file for the current user
|
||||
* @param { string } file The name of the userdata file to delete
|
||||
*/
|
||||
async deleteUserData(file) {
|
||||
async deleteUserData(file: string) {
|
||||
const resp = await this.fetchApi(`/userdata/${encodeURIComponent(file)}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
@@ -549,7 +553,11 @@ class ComfyApi extends EventTarget {
|
||||
* @param { string } source The userdata file to move
|
||||
* @param { string } dest The destination for the file
|
||||
*/
|
||||
async moveUserData(source, dest, options = { overwrite: false }) {
|
||||
async moveUserData(
|
||||
source: string,
|
||||
dest: string,
|
||||
options = { overwrite: false }
|
||||
) {
|
||||
const resp = await this.fetchApi(
|
||||
`/userdata/${encodeURIComponent(source)}/move/${encodeURIComponent(dest)}?overwrite=${options?.overwrite}`,
|
||||
{
|
||||
@@ -565,7 +573,7 @@ class ComfyApi extends EventTarget {
|
||||
* @param { string } dir The directory in which to list files
|
||||
* @param { boolean } [recurse] If the listing should be recursive
|
||||
* @param { true } [split] If the paths should be split based on the os path separator
|
||||
* @returns { Promise<string[][]>> } The list of split file paths in the format [fullPath, ...splitPath]
|
||||
* @returns { Promise<string[][]> } The list of split file paths in the format [fullPath, ...splitPath]
|
||||
*/
|
||||
/**
|
||||
* @overload
|
||||
@@ -575,6 +583,16 @@ class ComfyApi extends EventTarget {
|
||||
* @param { false | undefined } [split] If the paths should be split based on the os path separator
|
||||
* @returns { Promise<string[]> } The list of files
|
||||
*/
|
||||
async listUserData(
|
||||
dir: string,
|
||||
recurse: true,
|
||||
split?: boolean
|
||||
): Promise<string[][]>
|
||||
async listUserData(
|
||||
dir: string,
|
||||
recurse: false,
|
||||
split?: boolean
|
||||
): Promise<string[]>
|
||||
async listUserData(dir, recurse, split) {
|
||||
const resp = await this.fetchApi(
|
||||
`/userdata?${new URLSearchParams({
|
||||
|
||||
@@ -2186,7 +2186,7 @@ export class ComfyApp {
|
||||
|
||||
if (
|
||||
this.vueAppReady &&
|
||||
useSettingStore().get<boolean>('Comfy.Validation.Workflows')
|
||||
useSettingStore().get('Comfy.Validation.Workflows')
|
||||
) {
|
||||
graphData = await validateComfyWorkflow(graphData, /* onError=*/ alert)
|
||||
if (!graphData) return
|
||||
|
||||
@@ -4,6 +4,7 @@ import { prop } from '../../utils'
|
||||
import type { ComfyPopup } from './popup'
|
||||
import type { ComfyComponent } from '.'
|
||||
import type { ComfyApp } from '@/scripts/app'
|
||||
import { Settings } from '@/types/apiTypes'
|
||||
|
||||
type ComfyButtonProps = {
|
||||
icon?: string
|
||||
@@ -14,7 +15,7 @@ type ComfyButtonProps = {
|
||||
enabled?: boolean
|
||||
action?: (e: Event, btn: ComfyButton) => void
|
||||
classList?: ClassList
|
||||
visibilitySetting?: { id: string; showValue: any }
|
||||
visibilitySetting?: { id: keyof Settings; showValue: boolean }
|
||||
app?: ComfyApp
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ComfyDialog } from './dialog'
|
||||
import type { ComfyApp } from '../app'
|
||||
import type { Setting, SettingParams } from '@/types/settingTypes'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { Settings } from '@/types/apiTypes'
|
||||
|
||||
export class ComfySettingsDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
app: ComfyApp
|
||||
@@ -98,16 +99,19 @@ export class ComfySettingsDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
return id
|
||||
}
|
||||
|
||||
getSettingValue<T>(id: string, defaultValue?: T): T {
|
||||
getSettingValue<K extends keyof Settings>(
|
||||
id: K,
|
||||
defaultValue?: Settings[K]
|
||||
): Settings[K] {
|
||||
let value = this.settingsValues[this.getId(id)]
|
||||
if (value != null) {
|
||||
if (this.app.storageLocation === 'browser') {
|
||||
try {
|
||||
value = JSON.parse(value) as T
|
||||
value = JSON.parse(value)
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
return value ?? defaultValue
|
||||
return (value ?? defaultValue) as Settings[K]
|
||||
}
|
||||
|
||||
getSettingDefaultValue(id: string) {
|
||||
@@ -115,7 +119,10 @@ export class ComfySettingsDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
return param?.defaultValue
|
||||
}
|
||||
|
||||
async setSettingValueAsync(id: string, value: any) {
|
||||
async setSettingValueAsync<K extends keyof Settings>(
|
||||
id: K,
|
||||
value: Settings[K]
|
||||
) {
|
||||
const json = JSON.stringify(value)
|
||||
localStorage['Comfy.Settings.' + id] = json // backwards compatibility for extensions keep setting in storage
|
||||
|
||||
@@ -130,14 +137,14 @@ export class ComfySettingsDialog extends ComfyDialog<HTMLDialogElement> {
|
||||
await api.storeSetting(id, value)
|
||||
}
|
||||
|
||||
setSettingValue(id: string, value: any) {
|
||||
setSettingValue<K extends keyof Settings>(id: K, value: Settings[K]) {
|
||||
this.setSettingValueAsync(id, value).catch((err) => {
|
||||
alert(`Error saving setting '${id}'`)
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
refreshSetting(id: string) {
|
||||
refreshSetting(id: keyof Settings) {
|
||||
const value = this.getSettingValue(id)
|
||||
this.settingsLookup[id].onChange?.(value)
|
||||
this.#dispatchChange(id, value)
|
||||
|
||||
Reference in New Issue
Block a user