115 lines
3.3 KiB
TypeScript
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,
|
|
});
|
|
}
|
|
}
|