Add more Zod types to api.ts (#440)

This commit is contained in:
Björn Söderqvist
2024-08-15 16:45:40 +02:00
committed by GitHub
parent 1ff7a70579
commit 775f536d30
11 changed files with 165 additions and 57 deletions

View File

@@ -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({

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)