feat: enhance error handling with user-friendly messages and improve response parsing
This commit is contained in:
@@ -1,35 +1,53 @@
|
||||
/**
|
||||
* Utility för att parse HTTP-responses och extrahera tydliga felmeddelanden
|
||||
*/
|
||||
|
||||
// Deklarativ mappning av kända tekniska felsträngar → svenska meddelanden
|
||||
const MESSAGE_MAP: Array<{ match: string; label: string }> = [
|
||||
{ match: 'User_email_key', label: 'E-postadressen används redan av en annan användare.' },
|
||||
{ match: 'Det finns redan en annan produkt med detta namn', label: 'Det finns redan en annan produkt med detta namn. Välj ett unikt namn.' },
|
||||
];
|
||||
|
||||
function translateMessage(msg: string): string {
|
||||
const found = MESSAGE_MAP.find((entry) => msg.includes(entry.match));
|
||||
return found ? found.label : msg;
|
||||
}
|
||||
|
||||
export async function parseErrorResponse(response: Response): Promise<string> {
|
||||
const status = response.status;
|
||||
|
||||
|
||||
// Läs body som text en gång — Response.body kan bara konsumeras en gång
|
||||
let bodyText = '';
|
||||
try {
|
||||
const data = await response.json();
|
||||
|
||||
// Om backend skickade ett felmeddelande
|
||||
bodyText = await response.text();
|
||||
} catch {
|
||||
// Body kunde inte läsas
|
||||
}
|
||||
|
||||
// Försök tolka som JSON
|
||||
try {
|
||||
const data = JSON.parse(bodyText);
|
||||
|
||||
// NestJS class-validator kan returnera message som array
|
||||
if (Array.isArray(data.message) && data.message.length > 0) {
|
||||
return translateMessage(String(data.message[0]));
|
||||
}
|
||||
|
||||
if (typeof data.message === 'string') {
|
||||
// Produktnamns-dubblett
|
||||
if (data.message.includes('Det finns redan en annan produkt med detta namn')) {
|
||||
return 'Det finns redan en annan produkt med detta namn. Välj ett unikt namn.';
|
||||
}
|
||||
return data.message;
|
||||
return translateMessage(data.message);
|
||||
}
|
||||
if (data.error) {
|
||||
return data.error;
|
||||
|
||||
if (typeof data.error === 'string') {
|
||||
return translateMessage(data.error);
|
||||
}
|
||||
if (data.details) {
|
||||
return data.details;
|
||||
|
||||
if (typeof data.details === 'string') {
|
||||
return translateMessage(data.details);
|
||||
}
|
||||
} catch {
|
||||
// Inte JSON, försök text
|
||||
try {
|
||||
const text = await response.text();
|
||||
if (text && text.length < 200) {
|
||||
return text;
|
||||
}
|
||||
} catch {
|
||||
// Inget text-innehål
|
||||
// Inte JSON — använd råtexten om den är kortfattad
|
||||
if (bodyText && bodyText.length < 200) {
|
||||
return bodyText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +57,7 @@ export async function parseErrorResponse(response: Response): Promise<string> {
|
||||
401: 'Du är inte autentiserad. Logga in.',
|
||||
403: 'Du har inte behörighet till detta.',
|
||||
404: 'Resursen hittades inte.',
|
||||
409: 'Konflikten med befintlig data.',
|
||||
409: 'Konflikt med befintlig data.',
|
||||
422: 'Valideringen misslyckades. Kontrollera dina inmatningar.',
|
||||
500: 'Serverfel. Försök igen senare.',
|
||||
503: 'Tjänsten är inte tillgänglig.',
|
||||
@@ -47,8 +65,3 @@ export async function parseErrorResponse(response: Response): Promise<string> {
|
||||
|
||||
return defaultMessages[status] || `Fel (${status}). Försök igen senare.`;
|
||||
}
|
||||
|
||||
// Prisma unique constraint: email
|
||||
if (typeof data.message === 'string' && data.message.includes('User_email_key')) {
|
||||
return 'E-postadressen används redan av en annan användare.';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user