feat: Refactor API URL handling and add base path support (#131)

This commit is contained in:
samanhappy
2025-05-27 16:11:35 +08:00
committed by GitHub
parent 37bb3414c8
commit 268ce5cce6
18 changed files with 624 additions and 443 deletions

View File

@@ -1,7 +1,10 @@
import { AuthResponse, LoginCredentials, RegisterCredentials, ChangePasswordCredentials } from '../types';
// Base URL for API requests
const API_URL = '';
import {
AuthResponse,
LoginCredentials,
RegisterCredentials,
ChangePasswordCredentials,
} from '../types';
import { getApiUrl } from '../utils/api';
// Token key in localStorage
const TOKEN_KEY = 'mcphub_token';
@@ -24,7 +27,8 @@ export const removeToken = (): void => {
// Login user
export const login = async (credentials: LoginCredentials): Promise<AuthResponse> => {
try {
const response = await fetch(`${API_URL}/auth/login`, {
console.log(getApiUrl('/auth/login'));
const response = await fetch(getApiUrl('/auth/login'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -33,11 +37,11 @@ export const login = async (credentials: LoginCredentials): Promise<AuthResponse
});
const data: AuthResponse = await response.json();
if (data.success && data.token) {
setToken(data.token);
}
return data;
} catch (error) {
console.error('Login error:', error);
@@ -51,7 +55,7 @@ export const login = async (credentials: LoginCredentials): Promise<AuthResponse
// Register user
export const register = async (credentials: RegisterCredentials): Promise<AuthResponse> => {
try {
const response = await fetch(`${API_URL}/auth/register`, {
const response = await fetch(getApiUrl('/auth/register'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -60,11 +64,11 @@ export const register = async (credentials: RegisterCredentials): Promise<AuthRe
});
const data: AuthResponse = await response.json();
if (data.success && data.token) {
setToken(data.token);
}
return data;
} catch (error) {
console.error('Register error:', error);
@@ -78,16 +82,16 @@ export const register = async (credentials: RegisterCredentials): Promise<AuthRe
// Get current user
export const getCurrentUser = async (): Promise<AuthResponse> => {
const token = getToken();
if (!token) {
return {
success: false,
message: 'No authentication token',
};
}
try {
const response = await fetch(`${API_URL}/auth/user`, {
const response = await fetch(getApiUrl('/auth/user'), {
method: 'GET',
headers: {
'x-auth-token': token,
@@ -105,18 +109,20 @@ export const getCurrentUser = async (): Promise<AuthResponse> => {
};
// Change password
export const changePassword = async (credentials: ChangePasswordCredentials): Promise<AuthResponse> => {
export const changePassword = async (
credentials: ChangePasswordCredentials,
): Promise<AuthResponse> => {
const token = getToken();
if (!token) {
return {
success: false,
message: 'No authentication token',
};
}
try {
const response = await fetch(`${API_URL}/auth/change-password`, {
const response = await fetch(getApiUrl('/auth/change-password'), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -138,4 +144,4 @@ export const changePassword = async (credentials: ChangePasswordCredentials): Pr
// Logout user
export const logout = (): void => {
removeToken();
};
};

View File

@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react';
import { getToken } from './authService'; // Import getToken function
import { getApiUrl } from '../utils/api';
export interface LogEntry {
timestamp: number;
@@ -18,18 +19,18 @@ export const fetchLogs = async (): Promise<LogEntry[]> => {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch('/api/logs', {
const response = await fetch(getApiUrl('/logs'), {
headers: {
'x-auth-token': token
}
'x-auth-token': token,
},
});
const result = await response.json();
if (!result.success) {
throw new Error(result.error || 'Failed to fetch logs');
}
return result.data;
} catch (error) {
console.error('Error fetching logs:', error);
@@ -46,15 +47,15 @@ export const clearLogs = async (): Promise<void> => {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch('/api/logs', {
const response = await fetch(getApiUrl('/logs'), {
method: 'DELETE',
headers: {
'x-auth-token': token
}
'x-auth-token': token,
},
});
const result = await response.json();
if (!result.success) {
throw new Error(result.error || 'Failed to clear logs');
}
@@ -90,19 +91,19 @@ export const useLogs = () => {
}
// Connect to SSE endpoint with auth token in URL
eventSource = new EventSource(`/api/logs/stream?token=${token}`);
eventSource = new EventSource(getApiUrl(`/logs/stream?token=${token}`));
eventSource.onmessage = (event) => {
if (!isMounted) return;
try {
const data = JSON.parse(event.data);
if (data.type === 'initial') {
setLogs(data.logs);
setLoading(false);
} else if (data.type === 'log') {
setLogs(prevLogs => [...prevLogs, data.log]);
setLogs((prevLogs) => [...prevLogs, data.log]);
}
} catch (err) {
console.error('Error parsing SSE message:', err);
@@ -111,13 +112,13 @@ export const useLogs = () => {
eventSource.onerror = () => {
if (!isMounted) return;
if (eventSource) {
eventSource.close();
// Attempt to reconnect after a delay
setTimeout(connectToLogStream, 5000);
}
setError(new Error('Connection to log stream lost, attempting to reconnect...'));
};
} catch (err) {
@@ -149,4 +150,4 @@ export const useLogs = () => {
};
return { logs, loading, error, clearLogs: clearAllLogs };
};
};