Add new frontend - fix 9
This commit is contained in:
275
frontend/src/api/services/index.ts
Normal file
275
frontend/src/api/services/index.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
// src/api/services/index.ts
|
||||
/**
|
||||
* Main API Services Index
|
||||
* Central import point for all service modules
|
||||
*/
|
||||
|
||||
// Import all service classes
|
||||
export { AuthService, authService } from './AuthService';
|
||||
export { DataService, dataService } from './DataService';
|
||||
export { TrainingService, trainingService } from './TrainingService';
|
||||
export { ForecastingService, forecastingService } from './ForecastingService';
|
||||
export { NotificationService, notificationService } from './NotificationService';
|
||||
export { TenantService, tenantService } from './TenantService';
|
||||
|
||||
// Import base API client for custom implementations
|
||||
export { apiClient } from '../base/apiClient';
|
||||
|
||||
// Re-export all types from the main types file
|
||||
export * from '../types/api';
|
||||
|
||||
// Export additional service-specific types
|
||||
export type {
|
||||
DashboardStats,
|
||||
UploadResponse,
|
||||
DataValidation,
|
||||
} from './DataService';
|
||||
|
||||
export type {
|
||||
TrainingJobProgress,
|
||||
ModelMetrics,
|
||||
TrainingConfiguration,
|
||||
} from './TrainingService';
|
||||
|
||||
export type {
|
||||
SingleForecastRequest,
|
||||
BatchForecastRequest,
|
||||
ForecastAlert,
|
||||
QuickForecast,
|
||||
BatchForecastStatus,
|
||||
} from './ForecastingService';
|
||||
|
||||
export type {
|
||||
NotificationCreate,
|
||||
NotificationResponse,
|
||||
NotificationHistory,
|
||||
NotificationTemplate,
|
||||
NotificationStats,
|
||||
BulkNotificationRequest,
|
||||
BulkNotificationStatus,
|
||||
} from './NotificationService';
|
||||
|
||||
export type {
|
||||
TenantCreate,
|
||||
TenantUpdate,
|
||||
TenantSettings,
|
||||
TenantStats,
|
||||
TenantUser,
|
||||
InviteUser,
|
||||
} from './TenantService';
|
||||
|
||||
// Create a unified API object for convenience
|
||||
export const api = {
|
||||
auth: authService,
|
||||
data: dataService,
|
||||
training: trainingService,
|
||||
forecasting: forecastingService,
|
||||
notifications: notificationService,
|
||||
tenant: tenantService,
|
||||
} as const;
|
||||
|
||||
// Type for the unified API object
|
||||
export type ApiServices = typeof api;
|
||||
|
||||
// Service status type for monitoring
|
||||
export interface ServiceStatus {
|
||||
service: string;
|
||||
status: 'healthy' | 'degraded' | 'down';
|
||||
lastChecked: Date;
|
||||
responseTime?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// Health check utilities
|
||||
export class ApiHealthChecker {
|
||||
private static healthCheckEndpoints = {
|
||||
auth: '/auth/health',
|
||||
data: '/data/health',
|
||||
training: '/training/health',
|
||||
forecasting: '/forecasting/health',
|
||||
notifications: '/notifications/health',
|
||||
tenant: '/tenants/health',
|
||||
};
|
||||
|
||||
/**
|
||||
* Check health of all services
|
||||
*/
|
||||
static async checkAllServices(): Promise<Record<string, ServiceStatus>> {
|
||||
const results: Record<string, ServiceStatus> = {};
|
||||
|
||||
for (const [serviceName, endpoint] of Object.entries(this.healthCheckEndpoints)) {
|
||||
results[serviceName] = await this.checkService(serviceName, endpoint);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check health of a specific service
|
||||
*/
|
||||
static async checkService(serviceName: string, endpoint: string): Promise<ServiceStatus> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const response = await apiClient.get(endpoint, { timeout: 5000 });
|
||||
const responseTime = Date.now() - startTime;
|
||||
|
||||
return {
|
||||
service: serviceName,
|
||||
status: response.status === 200 ? 'healthy' : 'degraded',
|
||||
lastChecked: new Date(),
|
||||
responseTime,
|
||||
};
|
||||
} catch (error: any) {
|
||||
return {
|
||||
service: serviceName,
|
||||
status: 'down',
|
||||
lastChecked: new Date(),
|
||||
responseTime: Date.now() - startTime,
|
||||
error: error.message || 'Unknown error',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if core services are available
|
||||
*/
|
||||
static async checkCoreServices(): Promise<boolean> {
|
||||
const coreServices = ['auth', 'data', 'forecasting'];
|
||||
const results = await this.checkAllServices();
|
||||
|
||||
return coreServices.every(
|
||||
service => results[service]?.status === 'healthy'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Error handling utilities
|
||||
export class ApiErrorHandler {
|
||||
/**
|
||||
* Handle common API errors
|
||||
*/
|
||||
static handleError(error: any): never {
|
||||
if (error.response) {
|
||||
// Server responded with error status
|
||||
const { status, data } = error.response;
|
||||
|
||||
switch (status) {
|
||||
case 401:
|
||||
throw new Error('Authentication required. Please log in again.');
|
||||
case 403:
|
||||
throw new Error('You do not have permission to perform this action.');
|
||||
case 404:
|
||||
throw new Error('The requested resource was not found.');
|
||||
case 429:
|
||||
throw new Error('Too many requests. Please try again later.');
|
||||
case 500:
|
||||
throw new Error('Server error. Please try again later.');
|
||||
default:
|
||||
throw new Error(data?.message || `Request failed with status ${status}`);
|
||||
}
|
||||
} else if (error.request) {
|
||||
// Network error
|
||||
throw new Error('Network error. Please check your connection.');
|
||||
} else {
|
||||
// Other error
|
||||
throw new Error(error.message || 'An unexpected error occurred.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry failed requests with exponential backoff
|
||||
*/
|
||||
static async retryRequest<T>(
|
||||
requestFn: () => Promise<T>,
|
||||
maxRetries: number = 3,
|
||||
baseDelay: number = 1000
|
||||
): Promise<T> {
|
||||
let lastError: any;
|
||||
|
||||
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await requestFn();
|
||||
} catch (error: any) {
|
||||
lastError = error;
|
||||
|
||||
// Don't retry on certain errors
|
||||
if (error.response?.status === 401 || error.response?.status === 403) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Don't retry on last attempt
|
||||
if (attempt === maxRetries) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait before retrying with exponential backoff
|
||||
const delay = baseDelay * Math.pow(2, attempt);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
}
|
||||
|
||||
// Request cache utilities for performance optimization
|
||||
export class ApiCache {
|
||||
private static cache = new Map<string, { data: any; expires: number }>();
|
||||
|
||||
/**
|
||||
* Get cached response
|
||||
*/
|
||||
static get<T>(key: string): T | null {
|
||||
const cached = this.cache.get(key);
|
||||
|
||||
if (cached && cached.expires > Date.now()) {
|
||||
return cached.data;
|
||||
}
|
||||
|
||||
// Remove expired cache entry
|
||||
if (cached) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cached response
|
||||
*/
|
||||
static set(key: string, data: any, ttlMs: number = 300000): void { // 5 minutes default
|
||||
const expires = Date.now() + ttlMs;
|
||||
this.cache.set(key, { data, expires });
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache
|
||||
*/
|
||||
static clear(): void {
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear expired entries
|
||||
*/
|
||||
static cleanup(): void {
|
||||
const now = Date.now();
|
||||
for (const [key, value] of this.cache.entries()) {
|
||||
if (value.expires <= now) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cache key
|
||||
*/
|
||||
static generateKey(method: string, url: string, params?: any): string {
|
||||
const paramStr = params ? JSON.stringify(params) : '';
|
||||
return `${method}:${url}:${paramStr}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Export default as the unified API object
|
||||
export default api;
|
||||
Reference in New Issue
Block a user