- Add Python FastAPI backend with Pydantic validation - Port WhiskClient and MetaAIClient to Python - Create API routers for all endpoints - Add Swagger/ReDoc documentation at /docs - Update Dockerfile for multi-service container - Add lib/api.ts frontend client - Update README for V3
236 lines
5.8 KiB
TypeScript
236 lines
5.8 KiB
TypeScript
/**
|
|
* API Client for FastAPI Backend
|
|
*
|
|
* Centralized API calls to the FastAPI backend.
|
|
* Used by frontend components to call the new Python backend.
|
|
*/
|
|
|
|
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
|
|
|
|
// Types
|
|
export interface GenerateParams {
|
|
prompt: string;
|
|
aspectRatio?: string;
|
|
refs?: { subject?: string | string[]; scene?: string | string[]; style?: string | string[] };
|
|
preciseMode?: boolean;
|
|
imageCount?: number;
|
|
cookies: string;
|
|
}
|
|
|
|
export interface GeneratedImage {
|
|
data: string;
|
|
index?: number;
|
|
prompt: string;
|
|
aspectRatio: string;
|
|
}
|
|
|
|
export interface VideoParams {
|
|
prompt: string;
|
|
imageBase64?: string;
|
|
imageGenerationId?: string;
|
|
cookies: string;
|
|
}
|
|
|
|
export interface ReferenceUploadParams {
|
|
imageBase64: string;
|
|
mimeType: string;
|
|
category: string;
|
|
cookies: string;
|
|
}
|
|
|
|
export interface MetaGenerateParams {
|
|
prompt: string;
|
|
cookies?: string;
|
|
imageCount?: number;
|
|
aspectRatio?: string;
|
|
useMetaFreeWrapper?: boolean;
|
|
metaFreeWrapperUrl?: string;
|
|
}
|
|
|
|
// Helper to handle API responses
|
|
async function handleResponse<T>(response: Response): Promise<T> {
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ error: 'Request failed' }));
|
|
throw new Error(error.error || error.detail || `HTTP ${response.status}`);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
/**
|
|
* Generate images using Whisk API
|
|
*/
|
|
export async function generateImages(params: GenerateParams): Promise<{ images: GeneratedImage[] }> {
|
|
const response = await fetch(`${API_BASE}/generate`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(params)
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Generate video using Whisk API
|
|
*/
|
|
export async function generateVideo(params: VideoParams): Promise<{
|
|
success: boolean;
|
|
id?: string;
|
|
url?: string;
|
|
status?: string;
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/video/generate`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(params)
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Upload reference image
|
|
*/
|
|
export async function uploadReference(params: ReferenceUploadParams): Promise<{
|
|
success: boolean;
|
|
id: string;
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/references/upload`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(params)
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Generate images using Meta AI
|
|
*/
|
|
export async function generateMetaImages(params: MetaGenerateParams): Promise<{
|
|
success: boolean;
|
|
images: Array<{
|
|
data?: string;
|
|
url?: string;
|
|
prompt: string;
|
|
model: string;
|
|
aspectRatio: string;
|
|
}>;
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/meta/generate`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(params)
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Get prompts from library
|
|
*/
|
|
export async function getPrompts(): Promise<{
|
|
prompts: any[];
|
|
last_updated: string | null;
|
|
lastSync: number | null;
|
|
categories: Record<string, string[]>;
|
|
total_count: number;
|
|
sources: string[];
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/prompts`);
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Sync prompts from sources
|
|
*/
|
|
export async function syncPrompts(): Promise<{
|
|
success: boolean;
|
|
count: number;
|
|
added: number;
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/prompts/sync`, {
|
|
method: 'POST'
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Track prompt usage
|
|
*/
|
|
export async function trackPromptUse(promptId: number): Promise<{
|
|
success: boolean;
|
|
promptId: number;
|
|
useCount: number;
|
|
lastUsedAt: number;
|
|
}> {
|
|
const response = await fetch(`${API_BASE}/prompts/use`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ promptId })
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Get upload history
|
|
*/
|
|
export async function getHistory(category?: string): Promise<{
|
|
history: Array<{
|
|
id: string;
|
|
url: string;
|
|
originalName: string;
|
|
category: string;
|
|
mediaId?: string;
|
|
createdAt?: number;
|
|
}>;
|
|
}> {
|
|
const url = category ? `${API_BASE}/history?category=${category}` : `${API_BASE}/history`;
|
|
const response = await fetch(url);
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Upload to history
|
|
*/
|
|
export async function uploadToHistory(file: File, category: string, cookies?: string): Promise<{
|
|
id: string;
|
|
url: string;
|
|
originalName: string;
|
|
category: string;
|
|
mediaId?: string;
|
|
}> {
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
formData.append('category', category);
|
|
if (cookies) formData.append('cookies', cookies);
|
|
|
|
const response = await fetch(`${API_BASE}/history`, {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Delete history item
|
|
*/
|
|
export async function deleteHistoryItem(itemId: string): Promise<{ success: boolean }> {
|
|
const response = await fetch(`${API_BASE}/history/${itemId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Clear all history
|
|
*/
|
|
export async function clearHistory(): Promise<{ success: boolean }> {
|
|
const response = await fetch(`${API_BASE}/history`, {
|
|
method: 'DELETE'
|
|
});
|
|
return handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Health check
|
|
*/
|
|
export async function healthCheck(): Promise<{ status: string; service: string; version: string }> {
|
|
const response = await fetch(`${API_BASE}/health`);
|
|
return handleResponse(response);
|
|
}
|