187 lines
4.8 KiB
TypeScript
187 lines
4.8 KiB
TypeScript
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
|
|
export interface APIClientConfig {
|
|
baseURL: string;
|
|
timeout?: number;
|
|
headers?: Record<string, string>;
|
|
}
|
|
|
|
export interface AuthTokens {
|
|
accessToken: string;
|
|
refreshToken?: string;
|
|
}
|
|
|
|
class APIClient {
|
|
private client: AxiosInstance;
|
|
private tokens: AuthTokens | null = null;
|
|
|
|
constructor(config: APIClientConfig) {
|
|
this.client = axios.create({
|
|
baseURL: config.baseURL,
|
|
timeout: config.timeout || 30000,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...config.headers,
|
|
},
|
|
});
|
|
|
|
// Request interceptor - add auth token
|
|
this.client.interceptors.request.use((config) => {
|
|
if (this.tokens?.accessToken) {
|
|
config.headers.Authorization = `Bearer ${this.tokens.accessToken}`;
|
|
}
|
|
return config;
|
|
});
|
|
|
|
// Response interceptor - handle token refresh
|
|
this.client.interceptors.response.use(
|
|
(response) => response,
|
|
async (error) => {
|
|
if (error.response?.status === 401 && this.tokens?.refreshToken) {
|
|
try {
|
|
const newTokens = await this.refreshAccessToken();
|
|
this.setTokens(newTokens);
|
|
|
|
// Retry original request
|
|
error.config.headers.Authorization = `Bearer ${newTokens.accessToken}`;
|
|
return this.client.request(error.config);
|
|
} catch (refreshError) {
|
|
// Refresh failed, clear tokens
|
|
this.clearTokens();
|
|
throw refreshError;
|
|
}
|
|
}
|
|
throw error;
|
|
}
|
|
);
|
|
}
|
|
|
|
setTokens(tokens: AuthTokens) {
|
|
this.tokens = tokens;
|
|
}
|
|
|
|
clearTokens() {
|
|
this.tokens = null;
|
|
}
|
|
|
|
private async refreshAccessToken(): Promise<AuthTokens> {
|
|
const response = await this.client.post('/auth/refresh', {
|
|
refreshToken: this.tokens?.refreshToken,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
// Auth
|
|
async login(email: string, password: string) {
|
|
const response = await this.client.post('/auth/login', { email, password });
|
|
return response.data;
|
|
}
|
|
|
|
async register(email: string, password: string, username: string) {
|
|
const response = await this.client.post('/auth/register', {
|
|
email,
|
|
password,
|
|
username,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async getCurrentUser() {
|
|
const response = await this.client.get('/auth/me');
|
|
return response.data;
|
|
}
|
|
|
|
// Messages
|
|
async getConversations() {
|
|
const response = await this.client.get('/conversations');
|
|
return response.data;
|
|
}
|
|
|
|
async getMessages(conversationId: string, limit = 50, before?: string) {
|
|
const response = await this.client.get(`/messages/${conversationId}`, {
|
|
params: { limit, before },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async sendMessage(conversationId: string, content: string, contentType = 'text') {
|
|
const response = await this.client.post('/messages', {
|
|
conversationId,
|
|
content,
|
|
contentType,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
// Friends (Nexus)
|
|
async getFriends() {
|
|
const response = await this.client.get('/nexus/friends');
|
|
return response.data;
|
|
}
|
|
|
|
async sendFriendRequest(userId: string) {
|
|
const response = await this.client.post('/nexus/friends/request', { userId });
|
|
return response.data;
|
|
}
|
|
|
|
async acceptFriendRequest(requestId: string) {
|
|
const response = await this.client.post(`/nexus/friends/accept/${requestId}`);
|
|
return response.data;
|
|
}
|
|
|
|
// Calls
|
|
async initiateCall(recipientId: string, callType: 'voice' | 'video') {
|
|
const response = await this.client.post('/calls/initiate', {
|
|
recipientId,
|
|
callType,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async joinCall(callId: string) {
|
|
const response = await this.client.post(`/calls/join/${callId}`);
|
|
return response.data;
|
|
}
|
|
|
|
async leaveCall(callId: string) {
|
|
const response = await this.client.post(`/calls/leave/${callId}`);
|
|
return response.data;
|
|
}
|
|
|
|
// Premium
|
|
async checkDomainAvailability(domain: string) {
|
|
const response = await this.client.post('/premium/domains/check-availability', {
|
|
domain,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async subscribe(tier: string, paymentMethodId: string, billingPeriod: string) {
|
|
const response = await this.client.post('/premium/subscribe', {
|
|
tier,
|
|
paymentMethodId,
|
|
billingPeriod,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async getSubscription() {
|
|
const response = await this.client.get('/premium/subscription');
|
|
return response.data;
|
|
}
|
|
|
|
async getAnalytics(period: string = '30d') {
|
|
const response = await this.client.get('/premium/analytics', {
|
|
params: { period },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
// Generic request method
|
|
async request<T = any>(config: AxiosRequestConfig): Promise<T> {
|
|
const response = await this.client.request<T>(config);
|
|
return response.data;
|
|
}
|
|
}
|
|
|
|
export default APIClient;
|