ruch
Version:
Revolutionary React TypeScript CLI with hexagonal architecture & AI-powered development assistance. Create maintainable, scalable applications with domain-driven design and integrated AI tooling.
118 lines (104 loc) • 2.76 kB
text/typescript
/**
* HTTP client configuration and instance.
* @packageDocumentation
*/
import axios from 'axios';
import type { AxiosError, InternalAxiosRequestConfig, AxiosResponse } from 'axios';
/**
* Token storage interface for flexibility
*/
interface TokenStorage {
getToken(): string | null;
setToken(token: string): void;
removeToken(): void;
}
/**
* Default token storage using localStorage
*/
const defaultTokenStorage: TokenStorage = {
getToken: () => localStorage.getItem('auth_token'),
setToken: (token: string) => localStorage.setItem('auth_token', token),
removeToken: () => localStorage.removeItem('auth_token'),
};
/**
* HTTP client configuration
*/
interface HttpClientConfig {
baseURL?: string;
timeout?: number;
tokenStorage?: TokenStorage;
onUnauthorized?: () => void;
}
/**
* Create HTTP client with configuration
*/
export const createHttpClient = (config: HttpClientConfig = {}) => {
const {
baseURL = process.env.REACT_APP_API_URL || 'http://localhost:3000/api',
timeout = 10000,
tokenStorage = defaultTokenStorage,
onUnauthorized,
} = config;
const client = axios.create({
baseURL,
timeout,
headers: {
'Content-Type': 'application/json',
},
});
/**
* Request interceptor for authentication
*/
client.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = tokenStorage.getToken();
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error: AxiosError) => {
console.error('Request interceptor error:', error);
return Promise.reject(error);
}
);
/**
* Response interceptor for error handling
*/
client.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError) => {
// Handle authentication errors
if (error.response?.status === 401) {
tokenStorage.removeToken();
if (onUnauthorized) {
onUnauthorized();
} else {
console.warn('Unauthorized access - token removed');
}
}
// Log other errors for debugging
if (error.response?.status && error.response.status >= 500) {
console.error('Server error:', error.response.status, error.response.data);
}
return Promise.reject(error);
}
);
return client;
};
/**
* Default HTTP client instance
*/
export const httpClient = createHttpClient();
/**
* Utility function to update token storage
*/
export const updateAuthToken = (token: string) => {
defaultTokenStorage.setToken(token);
};
/**
* Utility function to clear authentication
*/
export const clearAuth = () => {
defaultTokenStorage.removeToken();
};