Cesar Mendivil 8b458a3ddf feat: add initial LiveKit Meet integration with utility scripts, configs, and core components
- Add Next.js app structure with base configs, linting, and formatting
- Implement LiveKit Meet page, types, and utility functions
- Add Docker, Compose, and deployment scripts for backend and token server
- Provide E2E and smoke test scaffolding with Puppeteer and Playwright helpers
- Include CSS modules and global styles for UI
- Add postMessage and studio integration utilities
- Update package.json with dependencies and scripts for development and testing
2025-11-20 12:50:38 -07:00

115 lines
3.1 KiB
TypeScript

import type { LoginCredentials, RegisterData, AuthResponse, ApiResponse } from '@avanzacast/shared-types';
import { getAuthHeader } from './auth';
// Access import.meta.env in a type-safe way even if the project doesn't declare the Vite env typing
const _env = (import.meta as any).env;
// En modo desarrollo, preferimos usar localhost:4000 cuando no se ha configurado VITE_API_URL
const DEFAULT_DEV_API = 'http://localhost:4000';
const API_BASE_URL = _env.VITE_API_URL || ((_env.MODE === 'development' || _env.DEV === true) ? DEFAULT_DEV_API : 'https://avanzacast-servertokens.bfzqqk.easypanel.host/api/v1');
/**
* Cliente HTTP para hacer peticiones a la API
*/
class ApiClient {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const url = `${this.baseUrl}${endpoint}`;
const headers = {
'Content-Type': 'application/json',
...getAuthHeader(),
...options.headers,
};
try {
const response = await fetch(url, {
...options,
headers,
});
const data = await response.json();
if (!response.ok) {
return {
success: false,
error: {
code: data.code || 'UNKNOWN_ERROR',
message: data.message || 'An error occurred',
details: data.details,
},
};
}
return {
success: true,
data,
};
} catch (error) {
return {
success: false,
error: {
code: 'NETWORK_ERROR',
message: error instanceof Error ? error.message : 'Network error',
},
};
}
}
async get<T>(endpoint: string): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, { method: 'GET' });
}
async post<T>(endpoint: string, data?: any): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined,
});
}
async put<T>(endpoint: string, data?: any): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, {
method: 'PUT',
body: data ? JSON.stringify(data) : undefined,
});
}
async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, { method: 'DELETE' });
}
// Auth endpoints
async login(credentials: LoginCredentials): Promise<ApiResponse<AuthResponse>> {
return this.post<AuthResponse>('/auth/login', credentials);
}
async register(data: RegisterData): Promise<ApiResponse<AuthResponse>> {
return this.post<AuthResponse>('/auth/register', data);
}
async logout(): Promise<ApiResponse<void>> {
return this.post<void>('/auth/logout');
}
async refreshToken(refreshToken: string): Promise<ApiResponse<AuthResponse>> {
return this.post<AuthResponse>('/auth/refresh', { refreshToken });
}
async getProfile(): Promise<ApiResponse<any>> {
return this.get('/auth/profile');
}
}
// Instancia única del cliente API
export const apiClient = new ApiClient(API_BASE_URL);
// Exportar cliente por defecto
export default apiClient;