import type {RgthreeModelInfo} from "typings/rgthree.js"; type ModelInfoType = "loras"; class RgthreeApi { private baseUrl: string; getCheckpointsPromise: Promise | null = null; getSamplersPromise: Promise | null = null; getSchedulersPromise: Promise | null = null; getLorasPromise: Promise | null = null; getWorkflowsPromise: Promise | null = null; constructor(baseUrl?: string) { this.baseUrl = baseUrl || "./rgthree/api"; } apiURL(route: string) { return `${this.baseUrl}${route}`; } fetchApi(route: string, options?: RequestInit) { return fetch(this.apiURL(route), options); } async fetchJson(route: string, options?: RequestInit) { const r = await this.fetchApi(route, options); return await r.json(); } async postJson(route: string, json: any) { const body = new FormData(); body.append("json", JSON.stringify(json)); return await rgthreeApi.fetchJson(route, {method: "POST", body}); } getLoras(force = false) { if (!this.getLorasPromise || force) { this.getLorasPromise = this.fetchJson("/loras", {cache: "no-store"}); } return this.getLorasPromise; } async fetchApiJsonOrNull(route: string, options?: RequestInit) { const response = await this.fetchJson(route, options); if (response.status === 200 && response.data) { return (response.data as T) || null; } return null; } /** * Fetches the lora information. * * @param light Whether or not to generate a json file if there isn't one. This isn't necessary if * we're just checking for values, but is more necessary when opening an info dialog. */ async getLorasInfo(lora: string, light?: boolean): Promise; async getLorasInfo(light?: boolean): Promise; async getLorasInfo(...args: any) { return this.getModelInfo("loras", ...args); } async refreshLorasInfo(file: string): Promise; async refreshLorasInfo(): Promise; async refreshLorasInfo(file?: string) { return this.refreshModelInfo("loras", file); } async clearLorasInfo(file?: string): Promise { return this.clearModelInfo("loras", file); } /** * Saves partial data sending it to the backend.. */ async saveLoraInfo( file: string, data: Partial, ): Promise { return this.saveModelInfo("loras", file, data); } private async getModelInfo(type: ModelInfoType, ...args: any) { const params = new URLSearchParams(); const isSingle = typeof args[0] == "string"; if (isSingle) { params.set("file", args[0]); } params.set("light", (isSingle ? args[1] : args[0]) === false ? "0" : "1"); const path = `/${type}/info?` + params.toString(); return await this.fetchApiJsonOrNull(path); } private async refreshModelInfo(type: ModelInfoType, file?: string) { const path = `/${type}/info/refresh` + (file ? `?file=${encodeURIComponent(file)}` : ""); const infos = await this.fetchApiJsonOrNull(path); return infos; } private async clearModelInfo(type: ModelInfoType, file?: string) { const path = `/${type}/info/clear` + (file ? `?file=${encodeURIComponent(file)}` : ""); await this.fetchApiJsonOrNull(path); return; } private async saveModelInfo( type: ModelInfoType, file: string, data: Partial, ): Promise { const body = new FormData(); body.append("json", JSON.stringify(data)); return await this.fetchApiJsonOrNull( `/${type}/info?file=${encodeURIComponent(file)}`, {cache: "no-store", method: "POST", body}, ); } } export const rgthreeApi = new RgthreeApi();