refactor(account): isRowMissing als gemeinsame Hilfsfunktion statt dreier Kopien

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 07:45:05 +00:00
1 parent 0ad51bf7c6
commit 04404ffdae
5 files changed
+40 -22

No files matched your search

+28 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { errorMessage, errorType, isInvalidLinkError, isUnauthorized, type ErrorContext } from './errors';
import { errorMessage, errorType, isInvalidLinkError, isRowMissing, isUnauthorized, type ErrorContext } from './errors';
/** Fehler wie vom SDK (AppwriteException): Felder code, type, message. */
const fail = (code: number, type: string, message = '') => ({ code, type, message });
@@ -149,6 +149,33 @@ describe('errorType', () => {
});
});
describe('isRowMissing', () => {
it('404 mit row_not_found heißt: die Zeile gibt es nicht (oder nicht für mich)', () => {
expect(isRowMissing(fail(404, 'row_not_found'))).toBe(true);
});
it('404 ohne Typ (leer oder fehlend) zählt ebenso', () => {
expect(isRowMissing(fail(404, ''))).toBe(true);
expect(isRowMissing({ code: 404 })).toBe(true);
});
it('eine fehlende Tabelle, Datenbank oder Datei ist ein echter Fehler, kein „Zeile weg“', () => {
for (const type of ['table_not_found', 'database_not_found', 'storage_file_not_found']) {
expect(isRowMissing(fail(404, type)), type).toBe(false);
}
});
it('andere Status und Nicht-Fehler nicht', () => {
expect(isRowMissing(fail(401, 'row_not_found'))).toBe(false);
expect(isRowMissing(fail(500, 'row_not_found'))).toBe(false);
expect(isRowMissing({ code: '404', type: 'row_not_found' })).toBe(false);
expect(isRowMissing(new TypeError('Failed to fetch'))).toBe(false);
expect(isRowMissing('row_not_found')).toBe(false);
expect(isRowMissing(null)).toBe(false);
expect(isRowMissing(undefined)).toBe(false);
});
});
describe('isInvalidLinkError (Passwort-neu-Seite)', () => {
it('Link-Fehler', () => {
expect(isInvalidLinkError(fail(401, 'user_invalid_token'))).toBe(true);
+9
View File
@@ -24,6 +24,15 @@ export function isUnauthorized(err: unknown): boolean {
return field(err, 'code') === 401;
}
/**
* „Die Zeile gibt es nicht (oder nicht für mich)“: 404 `row_not_found` (auch ein 404 ohne Typ). Eine fehlende Tabelle, Datenbank oder
* Datei ist dagegen ein echter Fehler. Die Einzel-Abfragen der Tabellen (`getGalleryCard`, `getLogo`, `getUsername`) werten damit 404 als „nicht da“.
*/
export function isRowMissing(err: unknown): boolean {
const type = field(err, 'type');
return field(err, 'code') === 404 && (type === 'row_not_found' || type === undefined || type === '');
}
/** Bei `general_argument_invalid` nennt die Nachricht den Parameter: „Invalid `email` param: …“. */
function invalidParam(err: unknown): string | null {
const message = field(err, 'message');
+1 -7
View File
@@ -9,6 +9,7 @@ import { API_MESSAGES } from '../i18n/api-messages';
import { msg, t } from '../i18n/i18n';
import { IDS, tables } from './appwrite';
import { currentUserId } from './auth';
import { isRowMissing } from './errors';
/** Wie im Dienst (deploy/api/common.js): 3–20 Zeichen, das erste ein Buchstabe oder eine Zahl, danach Buchstaben, Zahlen, `.`, `_`, `-`. */
export const USERNAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{2,19}$/;
@@ -112,13 +113,6 @@ export function myUsername(): string | null {
// ---- Lesen --------------------------------------------------------------------------------------------------
/** „Es gibt kein Profil (oder keines für mich)“; eine fehlende Tabelle oder Datenbank ist dagegen ein echter Fehler. */
function isRowMissing(err: unknown): boolean {
if (typeof err !== 'object' || err === null) return false;
const { code, type } = err as { code?: unknown; type?: unknown };
return code === 404 && (type === 'row_not_found' || type === undefined || type === '');
}
/**
* Der Name eines Kontos. Hat es kein Profil, ist das Ergebnis null (Appwrite antwortet mit 404); eine ID, die keine Appwrite-ID sein
* kann, ergibt null ohne Anfrage. Andere Fehler (Netz, Server) gehen durch.