Files
maestro/ui/src/api/pets.ts
T
oss-sync 77ee3bc426
CI / build-and-test (push) Waiting to run
sync: update from private repo (ddadfd71)
2026-07-08 23:35:00 +00:00

93 lines
2.9 KiB
TypeScript

// api.ts から分割(挙動不変): User Folder Pets。
// --- User Folder Pets ---
export interface PetSettings {
enabled: boolean;
activePetId: string | null;
size: 32 | 48 | 64 | 80;
position: 'bottom-right';
sound: boolean;
reducedMotion: boolean;
toolSparkEnabled: boolean;
workerPets: Record<string, string>;
}
export interface PetSummary {
id: string;
name: string;
description: string | null;
spriteFile: string | null;
previewFile: string | null;
frameWidth: number | null;
frameHeight: number | null;
gridCols: number | null;
gridRows: number | null;
updatedAt: string;
}
export interface PetDetail extends PetSummary {
manifest: Record<string, unknown>;
}
export interface PetsResponse {
pets: PetSummary[];
settings: PetSettings;
}
const PETS_BASE = '/api/users/me/pets';
export function petAssetUrl(petId: string, file: string): string {
return `${PETS_BASE}/${encodeURIComponent(petId)}/assets/${encodeURIComponent(file)}`;
}
export async function fetchPets(): Promise<PetsResponse> {
const res = await fetch(PETS_BASE, { credentials: 'include' });
const data = await res.json();
if (!res.ok) throw new Error(data?.error ?? 'Failed to fetch pets');
return data;
}
export async function fetchPet(petId: string): Promise<PetDetail> {
const res = await fetch(`${PETS_BASE}/${encodeURIComponent(petId)}`, { credentials: 'include' });
const data = await res.json();
if (!res.ok) throw new Error(data?.error ?? 'Failed to fetch pet');
return data.pet;
}
export async function importPet(file: File, options: { petId?: string; overwrite?: boolean } = {}): Promise<PetDetail> {
const params = new URLSearchParams();
params.set('filename', file.name);
if (options.petId) params.set('petId', options.petId);
if (options.overwrite) params.set('overwrite', 'true');
const res = await fetch(`${PETS_BASE}/import?${params.toString()}`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/zip' },
body: await file.arrayBuffer(),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data?.error ?? 'Failed to import pet');
return data.pet;
}
export async function deletePet(petId: string): Promise<void> {
const res = await fetch(`${PETS_BASE}/${encodeURIComponent(petId)}`, {
method: 'DELETE',
credentials: 'include',
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data?.error ?? 'Failed to delete pet');
}
export async function updatePetSettings(patch: Partial<PetSettings>): Promise<PetSettings> {
const res = await fetch(`${PETS_BASE}/settings`, {
method: 'PUT',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(patch),
});
const data = await res.json();
if (!res.ok) throw new Error(data?.error ?? 'Failed to update pet settings');
return data.settings;
}