# API Helper Utilities ## Overview The `APIHelper` class provides a comprehensive set of utilities for making API requests, handling authentication, and managing common operations across the application. ## Features - ✅ **Token Management**: Automatic JWT expiration checking - ✅ **API Requests**: Simplified fetch with error handling - ✅ **Data Extraction**: Smart array extraction from various response formats - ✅ **Health Monitoring**: Periodic API health checks - ✅ **UI Helpers**: Toast notifications, formatting utilities - ✅ **Performance**: Debounce and throttle functions --- ## Usage ### Basic Import ```javascript import { APIHelper } from '../../shared/js/utils/api-helper.js'; ``` --- ## API Methods ### Authentication #### `getHeaders()` Returns headers with optional Authorization token. Automatically checks token expiration. ```javascript const headers = APIHelper.getHeaders(); // Returns: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' } ``` #### `isTokenExpired(token)` Checks if a JWT token is expired. ```javascript const expired = APIHelper.isTokenExpired(token); // Returns: boolean ``` --- ### API Requests #### `fetchAPI(url, options)` Fetch data with automatic authorization and error handling. ```javascript // GET request const data = await APIHelper.fetchAPI('/api/market/top?limit=10'); // POST request const result = await APIHelper.fetchAPI('/api/sentiment/analyze', { method: 'POST', body: JSON.stringify({ text: 'Bitcoin is great!' }) }); ``` --- ### Data Processing #### `extractArray(data, keys)` Intelligently extract arrays from various response formats. ```javascript // Works with direct arrays const arr1 = APIHelper.extractArray([1, 2, 3]); // Works with nested data const arr2 = APIHelper.extractArray({ markets: [...] }, ['markets', 'data']); // Works with objects const arr3 = APIHelper.extractArray({ item1: {}, item2: {} }); ``` --- ### Health Monitoring #### `checkHealth()` Check API health status. ```javascript const health = await APIHelper.checkHealth(); // Returns: { status: 'online', healthy: true, data: {...} } ``` #### `monitorHealth(callback, interval)` Setup periodic health monitoring. ```javascript const intervalId = APIHelper.monitorHealth((health) => { console.log('API Status:', health.status); if (!health.healthy) { console.warn('API is down!'); } }, 30000); // Check every 30 seconds // Later, stop monitoring clearInterval(intervalId); ``` --- ### UI Utilities #### `showToast(message, type, duration)` Display toast notifications. ```javascript APIHelper.showToast('Operation successful!', 'success'); APIHelper.showToast('Something went wrong', 'error'); APIHelper.showToast('Please wait...', 'info'); APIHelper.showToast('Check your input', 'warning'); ``` #### `formatCurrency(amount, currency)` Format numbers as currency. ```javascript const formatted = APIHelper.formatCurrency(1234.56); // Returns: "$1,234.56" ``` #### `formatPercentage(value, decimals)` Format values as percentages. ```javascript const percent = APIHelper.formatPercentage(2.5); // Returns: "+2.50%" ``` #### `formatNumber(num, options)` Format numbers with locale settings. ```javascript const formatted = APIHelper.formatNumber(1000000); // Returns: "1,000,000" ``` --- ### Performance Utilities #### `debounce(func, wait)` Debounce function calls. ```javascript const debouncedSearch = APIHelper.debounce((query) => { console.log('Searching:', query); }, 300); // Call multiple times, only executes once after 300ms debouncedSearch('bitcoin'); debouncedSearch('ethereum'); debouncedSearch('solana'); ``` #### `throttle(func, limit)` Throttle function calls. ```javascript const throttledScroll = APIHelper.throttle(() => { console.log('Scroll event'); }, 100); window.addEventListener('scroll', throttledScroll); ``` --- ## Complete Example: Building a Page ```javascript import { APIHelper } from '../../shared/js/utils/api-helper.js'; class YourPage { constructor() { this.data = []; this.healthMonitor = null; } async init() { // Setup health monitoring this.healthMonitor = APIHelper.monitorHealth((health) => { console.log('API Health:', health.status); }); // Load data await this.loadData(); // Setup event listeners this.bindEvents(); } async loadData() { try { // Fetch data using APIHelper const response = await APIHelper.fetchAPI('/api/your-endpoint'); // Extract array safely this.data = APIHelper.extractArray(response, ['data', 'items']); // Render this.render(); // Show success APIHelper.showToast('Data loaded successfully!', 'success'); } catch (error) { console.error('Load error:', error); // Use fallback data this.data = this.getDemoData(); this.render(); // Show error APIHelper.showToast('Using demo data', 'warning'); } } bindEvents() { // Debounced search const searchInput = document.getElementById('search'); const debouncedSearch = APIHelper.debounce((query) => { this.filterData(query); }, 300); searchInput?.addEventListener('input', (e) => { debouncedSearch(e.target.value); }); } render() { // Render your data this.data.forEach(item => { const price = APIHelper.formatCurrency(item.price); const change = APIHelper.formatPercentage(item.change); console.log(`${item.name}: ${price} (${change})`); }); } getDemoData() { return [ { name: 'Bitcoin', price: 50000, change: 2.5 }, { name: 'Ethereum', price: 3000, change: -1.2 } ]; } destroy() { // Cleanup if (this.healthMonitor) { clearInterval(this.healthMonitor); } } } // Initialize const page = new YourPage(); page.init(); ``` --- ## Best Practices ### 1. Always Use APIHelper for Fetch Requests ```javascript // ✅ Good const data = await APIHelper.fetchAPI('/api/endpoint'); // ❌ Avoid const response = await fetch('/api/endpoint'); const data = await response.json(); ``` ### 2. Extract Arrays Safely ```javascript // ✅ Good const items = APIHelper.extractArray(response, ['items', 'data']); // ❌ Avoid (can fail) const items = response.items; ``` ### 3. Use Debounce for User Input ```javascript // ✅ Good const debouncedHandler = APIHelper.debounce(handler, 300); input.addEventListener('input', debouncedHandler); // ❌ Avoid (too many calls) input.addEventListener('input', handler); ``` ### 4. Monitor API Health ```javascript // ✅ Good APIHelper.monitorHealth((health) => { updateUI(health.status); }); // ❌ Avoid (no health awareness) // Just hope the API is up ``` --- ## Token Expiration The `APIHelper` automatically checks JWT token expiration: 1. **On Every Request**: Before adding Authorization header 2. **Automatic Removal**: Expired tokens are removed from localStorage 3. **Graceful Degradation**: Requests continue without auth if token expired ```javascript // Token is checked automatically const data = await APIHelper.fetchAPI('/api/protected-route'); // If token expired, it's removed and request proceeds without auth ``` --- ## Error Handling All `APIHelper` methods handle errors gracefully: ```javascript try { const data = await APIHelper.fetchAPI('/api/endpoint'); // Use data } catch (error) { // Error is already logged by APIHelper // Use fallback data const data = getDemoData(); } ``` --- ## Browser Compatibility - ✅ Modern browsers (ES6+ modules) - ✅ Chrome 61+ - ✅ Firefox 60+ - ✅ Safari 11+ - ✅ Edge 16+ --- ## License Part of Crypto Monitor ULTIMATE project.