// Created by: Claude // Date: 2026-01-03 // Purpose: Service API pour les appels au serveur Mesh // Refs: client/CLAUDE.md, docs/protocol_events_v_2.md import axios, { AxiosInstance } from 'axios' import { useAuthStore } from '../stores/authStore' // URL du serveur (à configurer via variable d'environnement) const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000' /** * Instance Axios configurée pour l'API Mesh. */ const apiClient: AxiosInstance = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, }) /** * Intercepteur pour ajouter le token d'authentification à chaque requête. */ apiClient.interceptors.request.use( (config) => { const token = useAuthStore.getState().token if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, (error) => Promise.reject(error) ) /** * Intercepteur pour gérer les erreurs d'authentification. */ apiClient.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // Token expiré ou invalide, déconnecter l'utilisateur useAuthStore.getState().logout() window.location.href = '/login' } return Promise.reject(error) } ) // ==================== Types ==================== export interface RegisterRequest { username: string password: string email?: string } export interface LoginRequest { username: string password: string } export interface AuthResponse { access_token: string token_type: string user_id: string username: string } export interface User { user_id: string username: string email?: string } export interface Room { room_id: string name: string owner_user_id: string created_at: string } export interface RoomMember { user_id: string username: string role: 'owner' | 'member' | 'guest' presence: 'online' | 'busy' | 'offline' } export interface CapabilityTokenRequest { room_id: string capabilities: string[] target_peer_id?: string } export interface CapabilityTokenResponse { capability_token: string expires_in: number } // ==================== API Functions ==================== /** * Authentification et gestion utilisateur. */ export const authApi = { /** * Enregistrer un nouvel utilisateur. */ register: async (data: RegisterRequest): Promise => { const response = await apiClient.post('/api/auth/register', data) return response.data }, /** * Se connecter. */ login: async (data: LoginRequest): Promise => { const response = await apiClient.post('/api/auth/login', data) return response.data }, /** * Récupérer les informations de l'utilisateur courant. */ getMe: async (): Promise => { const response = await apiClient.get('/api/auth/me') return response.data }, /** * Demander un capability token. */ requestCapability: async (data: CapabilityTokenRequest): Promise => { const response = await apiClient.post( '/api/auth/capability', data ) return response.data }, } /** * Gestion des rooms. */ export const roomsApi = { /** * Créer une nouvelle room. */ create: async (name: string): Promise => { const response = await apiClient.post('/api/rooms/', { name }) return response.data }, /** * Lister toutes les rooms accessibles. */ list: async (): Promise => { const response = await apiClient.get('/api/rooms/') return response.data }, /** * Récupérer les détails d'une room. */ get: async (roomId: string): Promise => { const response = await apiClient.get(`/api/rooms/${roomId}`) return response.data }, /** * Récupérer les membres d'une room. */ getMembers: async (roomId: string): Promise => { const response = await apiClient.get(`/api/rooms/${roomId}/members`) return response.data }, /** * Ajouter un membre à une room. */ addMember: async (roomId: string, username: string): Promise => { const response = await apiClient.post(`/api/rooms/${roomId}/members`, { username, }) return response.data }, } /** * Gestion des sessions P2P. */ export const p2pApi = { /** * Créer une session P2P. */ createSession: async (data: { room_id: string target_peer_id: string kind: 'file' | 'folder' | 'terminal' capabilities: string[] }) => { const response = await apiClient.post('/api/p2p/session', data) return response.data }, /** * Lister les sessions P2P actives. */ listSessions: async () => { const response = await apiClient.get('/api/p2p/sessions') return response.data }, /** * Fermer une session P2P. */ closeSession: async (sessionId: string) => { const response = await apiClient.delete(`/api/p2p/session/${sessionId}`) return response.data }, } export default apiClient