daisy-client / src /api /client.ts
Jessedbrown's picture
feat/init-daisy-client
6d643ca
Raw History Blame Contribute Delete
1.75 kB
import axios, {
AxiosError,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios';
import { API_CONFIG } from '@/lib/config';
import { ApiError, NetworkError } from '@/lib/errors';
import { HTTP_STATUS, STORAGE_KEYS } from '@/utils/constants';
// Create axios instance
export const apiClient = axios.create({
baseURL: API_CONFIG.BASE_URL,
headers: {
'Content-Type': 'application/json',
},
timeout: API_CONFIG.TIMEOUT,
});
// Request interceptor
apiClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// Add auth token if available
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error: unknown) =>
Promise.reject(error instanceof Error ? error : new Error(String(error)))
);
// Response interceptor
apiClient.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError) => {
const statusCode = error.response?.status;
const responseData = error.response?.data as Record<string, unknown>;
const message =
typeof responseData?.message === 'string'
? responseData.message
: error.message;
const code =
typeof responseData?.code === 'string' ? responseData.code : undefined;
// Handle specific error types
if (!error.response) {
// Network error
throw new NetworkError('Network connection failed', 0);
}
if (statusCode && statusCode >= HTTP_STATUS.BAD_REQUEST) {
throw new ApiError(
message,
statusCode,
code,
responseData?.details as Record<string, unknown> | undefined
);
}
return Promise.reject(error);
}
);