Initial commit: MVP structure + Cursor documentation + Onboarding components
This commit is contained in:
83
src/api/client.ts
Normal file
83
src/api/client.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
// API Client для MicroDAO
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'https://api.microdao.xyz';
|
||||
|
||||
export class ApiError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public status: number,
|
||||
public data?: unknown
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'ApiError';
|
||||
}
|
||||
}
|
||||
|
||||
async function getAuthToken(): Promise<string | null> {
|
||||
// Перевіряємо localStorage або httpOnly cookie
|
||||
return localStorage.getItem('auth_token');
|
||||
}
|
||||
|
||||
async function fetchApi(
|
||||
endpoint: string,
|
||||
options: RequestInit = {}
|
||||
): Promise<Response> {
|
||||
const token = await getAuthToken();
|
||||
|
||||
const headers: HeadersInit = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const url = endpoint.startsWith('http') ? endpoint : `${API_BASE_URL}${endpoint}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new ApiError(
|
||||
errorData.message || `HTTP ${response.status}: ${response.statusText}`,
|
||||
response.status,
|
||||
errorData
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function apiGet<T>(endpoint: string): Promise<T> {
|
||||
const response = await fetchApi(endpoint, { method: 'GET' });
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function apiPost<T>(endpoint: string, data?: unknown): Promise<T> {
|
||||
const response = await fetchApi(endpoint, {
|
||||
method: 'POST',
|
||||
body: data ? JSON.stringify(data) : undefined,
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function apiPatch<T>(endpoint: string, data: unknown): Promise<T> {
|
||||
const response = await fetchApi(endpoint, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function apiDelete<T>(endpoint: string): Promise<T> {
|
||||
const response = await fetchApi(endpoint, { method: 'DELETE' });
|
||||
if (response.status === 204) {
|
||||
return {} as T;
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user