Files
kickkingsadmin/src/lib/card-gen/preset-api.ts
T
2026-09-14 13:23:14 +00:00

115 lines
3.3 KiB
TypeScript

import type { GenerateConfig } from "@/lib/card-gen/id-config";
import { savePreset, type CardPreset } from "@/lib/card-gen/local-store";
export type ServerPresetMeta = {
id: string;
name: string;
config: GenerateConfig;
imageName: string;
hasImage: boolean;
fontName: string | null;
hasFont: boolean;
createdAt: number;
updatedAt: number;
};
async function readError(res: Response): Promise<string> {
const body = (await res.json().catch(() => null)) as { error?: string } | null;
return body?.error || `Request failed (${res.status})`;
}
export async function fetchServerPresetList(): Promise<ServerPresetMeta[]> {
const res = await fetch("/api/founders-card/presets", { cache: "no-store" });
if (!res.ok) throw new Error(await readError(res));
const body = (await res.json()) as { presets?: ServerPresetMeta[] };
return Array.isArray(body.presets) ? body.presets : [];
}
async function fileFromEndpoint(
url: string,
fallbackName: string,
): Promise<File | null> {
const res = await fetch(url, { cache: "no-store" });
if (!res.ok) return null;
const blob = await res.blob();
if (blob.size === 0) return null;
const name =
/filename="([^"]+)"/i.exec(res.headers.get("content-disposition") ?? "")?.[1] ??
fallbackName;
return new File([blob], name, {
type: blob.type || "application/octet-stream",
});
}
export async function fetchServerPresets(): Promise<CardPreset[]> {
const list = await fetchServerPresetList();
const out: CardPreset[] = [];
for (const meta of list) {
const image = meta.hasImage
? await fileFromEndpoint(
`/api/founders-card/presets/${meta.id}/image`,
meta.imageName || "base.png",
)
: null;
const font = meta.hasFont
? await fileFromEndpoint(
`/api/founders-card/presets/${meta.id}/font`,
meta.fontName || "custom.ttf",
)
: null;
out.push({
id: meta.id,
name: meta.name,
config: meta.config,
image,
font,
createdAt: meta.createdAt,
updatedAt: meta.updatedAt,
});
}
return out;
}
export async function pushPresetToServer(input: {
id?: string;
name: string;
config: GenerateConfig;
image: File | null;
font: File | null;
}): Promise<ServerPresetMeta> {
const fd = new FormData();
fd.append("name", input.name);
fd.append("config", JSON.stringify(input.config));
if (input.id) fd.append("id", input.id);
if (input.image) fd.append("image", input.image);
if (input.font) fd.append("font", input.font);
if (!input.font) fd.append("clearFont", "1");
const res = await fetch("/api/founders-card/presets", {
method: "POST",
body: fd,
});
if (!res.ok) throw new Error(await readError(res));
return (await res.json()) as ServerPresetMeta;
}
export async function deleteServerPreset(id: string): Promise<void> {
const res = await fetch(`/api/founders-card/presets/${id}`, {
method: "DELETE",
});
if (!res.ok && res.status !== 404) throw new Error(await readError(res));
}
export async function cacheServerPresetsLocally(
presets: CardPreset[],
): Promise<void> {
for (const preset of presets) {
await savePreset({
id: preset.id,
name: preset.name,
config: preset.config,
image: preset.image,
font: preset.font,
});
}
}