- 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
115 lines
3.1 KiB
TypeScript
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;
|