Really-amin's picture
Upload 577 files
b190b45 verified
# 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 <token>' }
```
#### `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.