eletrotupi / tcc/ commit / 4afa669

frontend: write a decent error handling for api issues

Pedro Lucas Porcellis porcellis@eletrotupi.com 29 days ago 4afa6690e7fdf56346236182ffc75bb984eb9441
Parents: 409c375
2 file(s) changed
  • frontend/lib/api/client.ts +25 -4
  • frontend/lib/api/index.ts +1 -1
frontend/lib/api/client.ts
1 1
import * as SecureStore from "expo-secure-store";
2 +

3 +
export class ApiError extends Error {
4 +
  status: number;
5 +
  fields?: Record<string, string>;
6 +

7 +
  constructor(message: string, status: number, fields?: Record<string, string>) {
8 +
    super(message);
9 +
    this.name = 'ApiError';
10 +
    this.status = status;
11 +
    this.fields = fields;
12 +
  }
13 +
}
2 14
import {
3 15
  User,
4 16
  AuthResponse,
5 17
  VerifyTokenResponse,
6 18
  SignUpPayload,
▸ 87 unchanged lines
94 106
        ...(!isFormData && { "Content-Type": "application/json" }),
95 107
        ...options.headers,
96 108
      },
97 109
    };
98 110

99 -
    const response = await fetch(`${API_BASE_URL}${endpoint}`, config);
111 +
    let response: Response;
112 +
    try {
113 +
      response = await fetch(`${API_BASE_URL}${endpoint}`, config);
114 +
    } catch {
115 +
      throw new ApiError("Sem conexão com o servidor", 0);
116 +
    }
100 117

101 118
    if (!response.ok) {
102 119
      if (response.status === 401) {
103 120
        this.onUnauthorizedCallback?.();
104 121
      }
105 122

106 -
      const error = await response
123 +
      const body = await response
107 124
        .json()
108 125
        .catch(() => ({ error: "Network error" }));
109 126

110 -
      console.error("[API]: ", error, response.status);
127 +
      console.error("[API]: ", body, response.status);
111 128

112 -
      throw new Error(error.error || `HTTP ${response.status}`);
129 +
      throw new ApiError(
130 +
        body.error || `HTTP ${response.status}`,
131 +
        response.status,
132 +
        body.fields,
133 +
      );
113 134
    }
114 135

115 136
    return response.json();
116 137
  }
117 138

▸ 340 unchanged lines
458 479
    return this.request(`/triggers/${triggerId}/link-mood/${moodId}`, { method: 'DELETE' });
459 480
  }
460 481
}
461 482

462 483
export const apiClient = new ApiClient();
frontend/lib/api/index.ts
1 -
export { apiClient } from "@/lib/api/client";
1 +
export { apiClient, ApiError } from "@/lib/api/client";
2 2

3 3
export type {
4 4
  User,
5 5
  AuthResponse,
6 6
  PaginatedResponse,
▸ 37 unchanged lines
44 44
  TriggerMoodLink,
45 45
  TriggerMoodLinkWithMood,
46 46
  TriggerMoodLinkWithTrigger,
47 47
  LinkMoodPayload,
48 48
} from "@/lib/api/types";