Files
PBandDev-comfyui-ping/src/api.ts
T

152 lines
3.4 KiB
TypeScript

export interface FetchApiClient {
fetchApi: (route: string, options?: RequestInit) => Promise<Response>;
}
export interface SoundCatalogEntry {
name: string;
}
export interface SoundCatalogPayload {
sounds: SoundCatalogEntry[];
}
export type SoundOptionId = string;
export interface RuntimeNotificationSettings {
enabled: boolean;
notify_mode: "every_prompt" | "queue_drained";
success_enabled: boolean;
failure_enabled: boolean;
success_sound: string;
failure_sound: string;
volume: number;
}
export const SOUND_CATALOG_ROUTE = "/comfyui-ping/sounds";
export const SOUND_UPLOAD_ROUTE = "/comfyui-ping/sounds/upload";
export const SETTINGS_ROUTE = "/comfyui-ping/settings";
export function toSoundOptionId(entry: SoundCatalogEntry): SoundOptionId {
return entry.name;
}
export function normalizeSoundOptionId(
soundId: string | null | undefined
): SoundOptionId | null {
if (!soundId) {
return null;
}
if (soundId.startsWith("bundled:") || soundId.startsWith("custom:")) {
return soundId.split(":")[1] ?? null;
}
return soundId;
}
export function parseSoundOptionId(soundId: string): SoundCatalogEntry {
const normalizedSoundId = normalizeSoundOptionId(soundId);
if (!normalizedSoundId) {
throw new Error("Missing sound option id");
}
return {
name: normalizedSoundId,
};
}
export function buildSoundCatalogRoute(): string {
return SOUND_CATALOG_ROUTE;
}
export function buildSoundUploadRoute(): string {
return SOUND_UPLOAD_ROUTE;
}
export function buildSettingsRoute(): string {
return SETTINGS_ROUTE;
}
export function buildSoundFileRoute(entry: SoundCatalogEntry): string {
return `${SOUND_CATALOG_ROUTE}/${encodeURIComponent(entry.name)}`;
}
export function parseSoundCatalogPayload(input: {
sounds?: Array<{
name?: string;
}>;
}): SoundCatalogPayload {
const sounds = input.sounds ?? [];
return {
sounds: sounds.flatMap((entry) => {
if (typeof entry.name !== "string") {
return [];
}
return [
{
name: entry.name,
},
];
}),
};
}
async function parseCatalogResponse(
response: Response
): Promise<SoundCatalogPayload> {
if (!response.ok) {
throw new Error(`Sound catalog request failed with status ${response.status}`);
}
const payload: {
sounds?: Array<{
name?: string;
}>;
} = await response.json();
return parseSoundCatalogPayload(payload);
}
export async function fetchSoundCatalog(
client: FetchApiClient
): Promise<SoundCatalogPayload> {
return parseCatalogResponse(
await client.fetchApi(buildSoundCatalogRoute(), undefined)
);
}
export async function uploadSoundFile(
client: FetchApiClient,
file: File
): Promise<SoundCatalogPayload> {
const formData = new FormData();
formData.append("file", file);
return parseCatalogResponse(
await client.fetchApi(buildSoundUploadRoute(), {
body: formData,
method: "POST",
})
);
}
export async function storeRuntimeSettings(
client: FetchApiClient,
settings: RuntimeNotificationSettings
): Promise<RuntimeNotificationSettings> {
const response = await client.fetchApi(buildSettingsRoute(), {
body: JSON.stringify(settings),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
if (!response.ok) {
throw new Error(`Settings request failed with status ${response.status}`);
}
return (await response.json()) as RuntimeNotificationSettings;
}