Files
mesh/client/src/services/api.ts
T
Gilles Soulier 1d177e96a6 first
2026-01-05 13:20:54 +01:00

226 lines
5.0 KiB
TypeScript

// 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<AuthResponse> => {
const response = await apiClient.post<AuthResponse>('/api/auth/register', data)
return response.data
},
/**
* Se connecter.
*/
login: async (data: LoginRequest): Promise<AuthResponse> => {
const response = await apiClient.post<AuthResponse>('/api/auth/login', data)
return response.data
},
/**
* Récupérer les informations de l'utilisateur courant.
*/
getMe: async (): Promise<User> => {
const response = await apiClient.get<User>('/api/auth/me')
return response.data
},
/**
* Demander un capability token.
*/
requestCapability: async (data: CapabilityTokenRequest): Promise<CapabilityTokenResponse> => {
const response = await apiClient.post<CapabilityTokenResponse>(
'/api/auth/capability',
data
)
return response.data
},
}
/**
* Gestion des rooms.
*/
export const roomsApi = {
/**
* Créer une nouvelle room.
*/
create: async (name: string): Promise<Room> => {
const response = await apiClient.post<Room>('/api/rooms/', { name })
return response.data
},
/**
* Lister toutes les rooms accessibles.
*/
list: async (): Promise<Room[]> => {
const response = await apiClient.get<Room[]>('/api/rooms/')
return response.data
},
/**
* Récupérer les détails d'une room.
*/
get: async (roomId: string): Promise<Room> => {
const response = await apiClient.get<Room>(`/api/rooms/${roomId}`)
return response.data
},
/**
* Récupérer les membres d'une room.
*/
getMembers: async (roomId: string): Promise<RoomMember[]> => {
const response = await apiClient.get<RoomMember[]>(`/api/rooms/${roomId}/members`)
return response.data
},
/**
* Ajouter un membre à une room.
*/
addMember: async (roomId: string, username: string): Promise<RoomMember> => {
const response = await apiClient.post<RoomMember>(`/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