Warnung vor doppelt abgelegten statischen Codes

Ein statischer Code traegt seinen Inhalt selbst — zweimal derselbe Inhalt
ergibt zweimal exakt dasselbe Bild. Bisher entstand der zweite Eintrag
stillschweigend.

Das Anlegen antwortet nun mit 409 und nennt den vorhandenen Eintrag samt
Namen und Datum; die Oberflaeche zeigt das als Warnung mit dem Knopf
"Trotzdem ablegen". Eine Rueckfrage, keine Sperre — zwei Fassungen
desselben Codes koennen gewollt sein.

Verglichen wird Typ und Inhalt innerhalb der Gruppe, nicht die Gestaltung.
Dynamische Codes bleiben aussen vor: zwei Kurz-Links auf dasselbe Ziel
sind der Normalfall, sobald getrennt gezaehlt werden soll.

ApiError traegt dafuer jetzt Status und Antwortkoerper — eine gemeldete
Dublette ist keine Sackgasse, sondern eine Rueckfrage.

Refs #6
This commit is contained in:
Florian Wilde
2026-08-21 02:53:23 +02:00
parent b96e9ddbe5
commit 60f46bcdb5
5 changed files with 218 additions and 30 deletions
+33 -14
View File
@@ -1,23 +1,42 @@
/** Kleine Hilfen für Aufrufe der eigenen API aus Client-Komponenten. */
async function readError(response: Response): Promise<string> {
async function readError(response: Response): Promise<ApiError> {
let body: unknown = null;
try {
const body: unknown = await response.json();
if (
body !== null &&
typeof body === "object" &&
"error" in body &&
typeof (body as { error: unknown }).error === "string"
) {
return (body as { error: string }).error;
}
body = await response.json();
} catch {
// Antwort ohne JSON-Körper — unten kommt die allgemeine Meldung.
}
return `Die Anfrage ist fehlgeschlagen (HTTP ${response.status}).`;
const message =
body !== null &&
typeof body === "object" &&
"error" in body &&
typeof (body as { error: unknown }).error === "string"
? (body as { error: string }).error
: `Die Anfrage ist fehlgeschlagen (HTTP ${response.status}).`;
return new ApiError(message, response.status, body);
}
export class ApiError extends Error {}
/**
* Fehler einer eigenen API-Antwort.
*
* Trägt neben der Meldung auch den Status und den Antwortkörper: Manche
* Fehler sind keine Sackgasse, sondern eine Rückfrage — etwa die gemeldete
* Dublette beim Ablegen, zu der die Oberfläche den vorhandenen Eintrag
* anzeigen will.
*/
export class ApiError extends Error {
readonly status: number;
readonly details: unknown;
constructor(message: string, status = 0, details: unknown = null) {
super(message);
this.status = status;
this.details = details;
}
}
export async function apiJson<T>(
url: string,
@@ -34,7 +53,7 @@ export async function apiJson<T>(
});
if (!response.ok) {
throw new ApiError(await readError(response));
throw await readError(response);
}
if (response.status === 204) {
return undefined as T;
@@ -55,7 +74,7 @@ export async function downloadFile(
});
if (!response.ok) {
throw new ApiError(await readError(response));
throw await readError(response);
}
const disposition = response.headers.get("Content-Disposition") ?? "";