cosmo/frontend/src/utils/api.ts

162 lines
4.6 KiB
TypeScript
Raw Normal View History

/**
* API utilities for fetching celestial data
*/
import axios from 'axios';
import type { CelestialDataResponse, BodyInfo } from '../types';
2025-11-30 02:43:47 +00:00
import { auth } from './auth';
2025-11-27 10:14:25 +00:00
// Dynamically determine the API base URL
// If VITE_API_BASE_URL is set, use it; otherwise use the current host with port 8000
const getApiBaseUrl = () => {
if (import.meta.env.VITE_API_BASE_URL) {
console.log('[API] Using VITE_API_BASE_URL:', import.meta.env.VITE_API_BASE_URL);
return import.meta.env.VITE_API_BASE_URL;
}
// Use the same host as the frontend, but with port 8000
const protocol = window.location.protocol;
const hostname = window.location.hostname;
const apiUrl = `${protocol}//${hostname}:8000/api`;
console.log('[API] Constructed API URL:', apiUrl);
console.log('[API] Protocol:', protocol, 'Hostname:', hostname);
return apiUrl;
};
const API_BASE_URL = getApiBaseUrl();
console.log('[API] Final API_BASE_URL:', API_BASE_URL);
export const api = axios.create({
baseURL: API_BASE_URL,
2025-11-29 15:10:00 +00:00
timeout: 120000, // Increase timeout to 120 seconds for historical data queries
});
2025-11-30 02:43:47 +00:00
// Add request interceptor for debugging and auth
2025-11-27 10:14:25 +00:00
api.interceptors.request.use(
(config) => {
console.log('[API Request]', config.method?.toUpperCase(), config.url, config.params);
2025-11-30 02:43:47 +00:00
// Add token if available
const token = auth.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
2025-11-27 10:14:25 +00:00
return config;
},
(error) => {
console.error('[API Request Error]', error);
return Promise.reject(error);
}
);
// Add response interceptor for debugging
api.interceptors.response.use(
(response) => {
console.log('[API Response]', response.config.url, response.status, 'Data:', response.data);
return response;
},
(error) => {
console.error('[API Error]', error.config?.url, error.message);
if (error.response) {
console.error('[API Error Response]', error.response.status, error.response.data);
} else if (error.request) {
console.error('[API Error Request]', error.request);
}
return Promise.reject(error);
}
);
/**
* Fetch celestial positions
*/
export async function fetchCelestialPositions(
startTime?: string,
endTime?: string,
step: string = '1d'
): Promise<CelestialDataResponse> {
const params: Record<string, string> = { step };
if (startTime) params.start_time = startTime;
if (endTime) params.end_time = endTime;
const response = await api.get<CelestialDataResponse>('/celestial/positions', {
params,
});
return response.data;
}
/**
* Fetch body information
*/
export async function fetchBodyInfo(bodyId: string): Promise<BodyInfo> {
const response = await api.get<BodyInfo>(`/celestial/info/${bodyId}`);
return response.data;
}
/**
* List all bodies
*/
export async function fetchAllBodies(): Promise<{ bodies: BodyInfo[] }> {
const response = await api.get('/celestial/list');
return response.data;
}
2025-11-29 15:10:00 +00:00
/**
* Fetch static data by category (constellation, galaxy, nebula, star, cluster)
*/
export async function fetchStaticData(category: string): Promise<{
category: string;
items: Array<{
id: number;
name: string;
name_zh: string;
data: any;
}>;
}> {
const response = await api.get(`/celestial/static/${category}`);
return response.data;
}
/**
* Get resource URL from backend
*/
export function getResourceUrl(type: 'texture' | 'model' | 'icon' | 'thumbnail' | 'data', filename: string): string {
const protocol = window.location.protocol;
const hostname = window.location.hostname;
const port = import.meta.env.VITE_API_BASE_URL ? '' : ':8000';
return `${protocol}//${hostname}${port}/upload/${type}/${filename}`;
}
/**
* Fetch resources for a celestial body
*/
export async function fetchBodyResources(bodyId: string, resourceType?: string): Promise<{
body_id: string;
resources: Array<{
id: number;
resource_type: string;
file_path: string;
file_size: number;
mime_type: string;
created_at: string;
}>;
}> {
const params: Record<string, string> = {};
if (resourceType) params.resource_type = resourceType;
const response = await api.get(`/celestial/resources/${bodyId}`, { params });
return response.data;
}
2025-11-30 02:43:47 +00:00
/**
* Auth API methods
*/
export async function login(username: string, password: string): Promise<any> {
const response = await api.post('/auth/login', { username, password });
return response.data;
}
export async function register(username: string, password: string, email?: string, full_name?: string): Promise<any> {
const response = await api.post('/auth/register', { username, password, email, full_name });
return response.data;
}