Files
ColaFlow-Web/lib/api/client.ts
Yaojia Wang 2ea3c93aa2 fix(frontend): Add comprehensive debugging for API connection issues
Enhanced error handling and debugging to diagnose API connection problems.

Changes:
- Added detailed console logging in API client (client.ts)
- Enhanced error display in projects page with troubleshooting steps
- Added logging in useProjects hook for better debugging
- Display API URL and error details on error screen
- Added retry button for easy error recovery

This will help diagnose why the backend API (localhost:5167) is not connecting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 09:12:00 +01:00

125 lines
2.9 KiB
TypeScript

const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:5000/api/v1';
// Log API URL for debugging
if (typeof window !== 'undefined') {
console.log('[API Client] API_URL:', API_URL);
console.log('[API Client] NEXT_PUBLIC_API_URL:', process.env.NEXT_PUBLIC_API_URL);
}
export class ApiError extends Error {
constructor(
public status: number,
message: string,
public data?: any
) {
super(message);
this.name = 'ApiError';
}
}
async function handleResponse<T>(response: Response): Promise<T> {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
const error = new ApiError(
response.status,
errorData.message || response.statusText,
errorData
);
console.error('[API Client] Request failed:', {
url: response.url,
status: response.status,
statusText: response.statusText,
errorData,
});
throw error;
}
if (response.status === 204) {
return {} as T;
}
return response.json();
}
export async function apiRequest<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const url = `${API_URL}${endpoint}`;
console.log('[API Client] Request:', {
method: options.method || 'GET',
url,
endpoint,
});
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
// Add auth token if available
if (typeof window !== 'undefined') {
const token = localStorage.getItem('accessToken');
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
}
// Merge with options headers
if (options.headers) {
Object.assign(headers, options.headers);
}
const config: RequestInit = {
...options,
headers,
};
try {
const response = await fetch(url, config);
const result = await handleResponse<T>(response);
console.log('[API Client] Response:', {
url,
status: response.status,
data: result,
});
return result;
} catch (error) {
console.error('[API Client] Network error:', {
url,
error: error instanceof Error ? error.message : String(error),
errorObject: error,
});
throw error;
}
}
export const api = {
get: <T>(endpoint: string, options?: RequestInit) =>
apiRequest<T>(endpoint, { ...options, method: 'GET' }),
post: <T>(endpoint: string, data?: any, options?: RequestInit) =>
apiRequest<T>(endpoint, {
...options,
method: 'POST',
body: JSON.stringify(data),
}),
put: <T>(endpoint: string, data?: any, options?: RequestInit) =>
apiRequest<T>(endpoint, {
...options,
method: 'PUT',
body: JSON.stringify(data),
}),
patch: <T>(endpoint: string, data?: any, options?: RequestInit) =>
apiRequest<T>(endpoint, {
...options,
method: 'PATCH',
body: JSON.stringify(data),
}),
delete: <T>(endpoint: string, options?: RequestInit) =>
apiRequest<T>(endpoint, { ...options, method: 'DELETE' }),
};