Dieselben Endpunkte bedienen Skripte und das eigene Frontend: erst wird ein Bearer-Token geprüft, sonst das Sitzungscookie. Sichtungsaktionen geben immer watchIds zurück — damit lässt sich genau diese Aktion über DELETE zurücknehmen, ohne raten zu müssen, was dazugehörte. Die OpenAPI-Beschreibung ist handgeschrieben statt aus Zod erzeugt: die Schnittstelle ist überschaubar, und ein Generator brächte eine weitere Abhängigkeit für einen Nutzen, den ein Dutzend Zeilen JSON auch hergeben.
34 lines
1.1 KiB
TypeScript
34 lines
1.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { withApi } from "@/lib/api";
|
|
import { exportCsv, exportJson } from "@/lib/transfer";
|
|
|
|
/**
|
|
* GET /api/v1/export?format=json|csv
|
|
*
|
|
* Vollständiger Export der eigenen Daten. JSON enthält zusätzlich Sichtungen
|
|
* und Universen, CSV ist die schlanke Tabellenform für Tabellenkalkulationen.
|
|
*/
|
|
export const GET = withApi(async (request, user) => {
|
|
const url = new URL(request.url);
|
|
const format = url.searchParams.get("format") === "csv" ? "csv" : "json";
|
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
|
|
if (format === "csv") {
|
|
const csv = await exportCsv(user.id);
|
|
return new NextResponse(csv, {
|
|
headers: {
|
|
"content-type": "text/csv; charset=utf-8",
|
|
"content-disposition": `attachment; filename="flimmer-${stamp}.csv"`,
|
|
},
|
|
});
|
|
}
|
|
|
|
const data = await exportJson(user.id);
|
|
return new NextResponse(JSON.stringify(data, null, 2), {
|
|
headers: {
|
|
"content-type": "application/json; charset=utf-8",
|
|
"content-disposition": `attachment; filename="flimmer-${stamp}.json"`,
|
|
},
|
|
});
|
|
});
|