- Migrated vanilla JS frontend to Vite + TypeScript - Modular architecture: views, components, utils, api, state - Three-panel layout: libraries (left), content (center), detail (right) - Group name resolution via hstTags (set_hst -> readable name) - Name priority: name_es -> alias -> ref -> hash truncated - D3.js lazy loading in GraphView - Hash-based routing - Deployed to tzzrdeck.me Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
39 lines
898 B
TypeScript
39 lines
898 B
TypeScript
import { API_BASE } from '@/config/index.ts';
|
|
|
|
interface FetchOptions {
|
|
method?: 'GET' | 'POST';
|
|
body?: Record<string, unknown>;
|
|
}
|
|
|
|
export async function apiClient<T>(
|
|
endpoint: string,
|
|
options: FetchOptions = {}
|
|
): Promise<T> {
|
|
const { method = 'GET', body } = options;
|
|
|
|
const config: RequestInit = {
|
|
method,
|
|
headers: body ? { 'Content-Type': 'application/json' } : undefined,
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
};
|
|
|
|
const response = await fetch(`${API_BASE}${endpoint}`, config);
|
|
if (!response.ok) {
|
|
throw new Error(`API Error: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
export async function apiClientSafe<T>(
|
|
endpoint: string,
|
|
options: FetchOptions = {},
|
|
fallback: T
|
|
): Promise<T> {
|
|
try {
|
|
return await apiClient<T>(endpoint, options);
|
|
} catch {
|
|
console.error(`API call failed: ${endpoint}`);
|
|
return fallback;
|
|
}
|
|
}
|