huge refactor to remove depenencie hell and add typesafe container

This commit is contained in:
Boki 2025-06-24 09:37:51 -04:00
parent 28b9822d55
commit 843a7b9b9b
148 changed files with 3603 additions and 2378 deletions

View file

@ -1,4 +1,3 @@
export { AddProviderMappingDialog } from './AddProviderMappingDialog';
export { AddExchangeDialog } from './AddExchangeDialog';
export { DeleteExchangeDialog } from './DeleteExchangeDialog';

View file

@ -133,4 +133,4 @@ interface BaseDialogProps {
export interface AddExchangeDialogProps extends BaseDialogProps {
onCreateExchange: (request: CreateExchangeRequest) => Promise<void>;
}
}

View file

@ -11,4 +11,4 @@ export { ProxyStatsCard } from './ProxyStatsCard';
export { StatusBadge, ConnectionStatus, HealthStatus, ServiceStatusIndicator } from './StatusBadge';
export { MetricCard } from './MetricCard';
export { ServiceCard } from './ServiceCard';
export { DatabaseCard } from './DatabaseCard';
export { DatabaseCard } from './DatabaseCard';

View file

@ -2,4 +2,4 @@
* Monitoring hooks exports
*/
export * from './useMonitoring';
export * from './useMonitoring';

View file

@ -2,16 +2,16 @@
* Custom hook for monitoring data
*/
import { useState, useEffect, useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { monitoringApi } from '../services/monitoringApi';
import type {
SystemHealth,
CacheStats,
QueueStats,
import type {
CacheStats,
DatabaseStats,
ServiceStatus,
ProxyStats,
SystemOverview
QueueStats,
ServiceStatus,
SystemHealth,
SystemOverview,
} from '../types';
export function useSystemHealth(refreshInterval: number = 5000) {
@ -33,7 +33,7 @@ export function useSystemHealth(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -62,7 +62,7 @@ export function useCacheStats(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -91,7 +91,7 @@ export function useQueueStats(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -120,7 +120,7 @@ export function useDatabaseStats(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -149,7 +149,7 @@ export function useServiceStatus(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -178,7 +178,7 @@ export function useProxyStats(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -207,7 +207,7 @@ export function useSystemOverview(refreshInterval: number = 5000) {
useEffect(() => {
fetchData();
if (refreshInterval > 0) {
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
@ -215,4 +215,4 @@ export function useSystemOverview(refreshInterval: number = 5000) {
}, [fetchData, refreshInterval]);
return { data, loading, error, refetch: fetchData };
}
}

View file

@ -5,4 +5,4 @@
export { MonitoringPage } from './MonitoringPage';
export * from './types';
export * from './hooks/useMonitoring';
export * from './services/monitoringApi';
export * from './services/monitoringApi';

View file

@ -2,14 +2,14 @@
* Monitoring API Service
*/
import type {
SystemHealth,
CacheStats,
QueueStats,
import type {
CacheStats,
DatabaseStats,
ServiceStatus,
ProxyStats,
SystemOverview
QueueStats,
ServiceStatus,
SystemHealth,
SystemOverview,
} from '../types';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:2003';
@ -125,4 +125,4 @@ export const monitoringApi = {
}
return response.json();
},
};
};

View file

@ -117,4 +117,4 @@ export interface SystemOverview {
architecture: string;
hostname: string;
};
}
}

View file

@ -1,42 +1,48 @@
/**
* Common formatting utilities for monitoring components
*/
export function formatUptime(ms: number): string {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) {return `${days}d ${hours % 24}h`;}
if (hours > 0) {return `${hours}h ${minutes % 60}m`;}
if (minutes > 0) {return `${minutes}m ${seconds % 60}s`;}
return `${seconds}s`;
}
export function formatBytes(bytes: number): string {
const gb = bytes / 1024 / 1024 / 1024;
if (gb >= 1) {
return gb.toFixed(2) + ' GB';
}
const mb = bytes / 1024 / 1024;
if (mb >= 1) {
return mb.toFixed(2) + ' MB';
}
const kb = bytes / 1024;
if (kb >= 1) {
return kb.toFixed(2) + ' KB';
}
return bytes + ' B';
}
export function formatNumber(num: number): string {
return num.toLocaleString();
}
export function formatPercentage(value: number, decimals: number = 1): string {
return `${value.toFixed(decimals)}%`;
}
/**
* Common formatting utilities for monitoring components
*/
export function formatUptime(ms: number): string {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) {
return `${days}d ${hours % 24}h`;
}
if (hours > 0) {
return `${hours}h ${minutes % 60}m`;
}
if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`;
}
return `${seconds}s`;
}
export function formatBytes(bytes: number): string {
const gb = bytes / 1024 / 1024 / 1024;
if (gb >= 1) {
return gb.toFixed(2) + ' GB';
}
const mb = bytes / 1024 / 1024;
if (mb >= 1) {
return mb.toFixed(2) + ' MB';
}
const kb = bytes / 1024;
if (kb >= 1) {
return kb.toFixed(2) + ' KB';
}
return bytes + ' B';
}
export function formatNumber(num: number): string {
return num.toLocaleString();
}
export function formatPercentage(value: number, decimals: number = 1): string {
return `${value.toFixed(decimals)}%`;
}

View file

@ -12,28 +12,29 @@ export function usePipeline() {
const [error, setError] = useState<string | null>(null);
const [lastJobResult, setLastJobResult] = useState<PipelineJobResult | null>(null);
const executeOperation = useCallback(async (
operation: () => Promise<PipelineJobResult>
): Promise<boolean> => {
try {
setLoading(true);
setError(null);
const result = await operation();
setLastJobResult(result);
if (!result.success) {
setError(result.error || 'Operation failed');
const executeOperation = useCallback(
async (operation: () => Promise<PipelineJobResult>): Promise<boolean> => {
try {
setLoading(true);
setError(null);
const result = await operation();
setLastJobResult(result);
if (!result.success) {
setError(result.error || 'Operation failed');
return false;
}
return true;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
setLastJobResult({ success: false, error: errorMessage });
return false;
} finally {
setLoading(false);
}
return true;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
setLastJobResult({ success: false, error: errorMessage });
return false;
} finally {
setLoading(false);
}
}, []);
},
[]
);
// Symbol sync operations
const syncQMSymbols = useCallback(
@ -53,7 +54,7 @@ export function usePipeline() {
);
const syncAllExchanges = useCallback(
(clearFirst: boolean = false) =>
(clearFirst: boolean = false) =>
executeOperation(() => pipelineApi.syncAllExchanges(clearFirst)),
[executeOperation]
);
@ -71,7 +72,7 @@ export function usePipeline() {
// Maintenance operations
const clearPostgreSQLData = useCallback(
(dataType: DataClearType = 'all') =>
(dataType: DataClearType = 'all') =>
executeOperation(() => pipelineApi.clearPostgreSQLData(dataType)),
[executeOperation]
);
@ -122,7 +123,8 @@ export function usePipeline() {
setError(result.error || 'Failed to get provider mapping stats');
return null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to get provider mapping stats';
const errorMessage =
err instanceof Error ? err.message : 'Failed to get provider mapping stats';
setError(errorMessage);
return null;
} finally {
@ -156,4 +158,4 @@ export function usePipeline() {
getExchangeStats,
getProviderMappingStats,
};
}
}

View file

@ -1,3 +1,3 @@
export { PipelinePage } from './PipelinePage';
export * from './hooks/usePipeline';
export * from './types';
export * from './types';

View file

@ -1,16 +1,9 @@
import type {
DataClearType,
PipelineJobResult,
PipelineStatsResult,
} from '../types';
import type { DataClearType, PipelineJobResult, PipelineStatsResult } from '../types';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:2003';
class PipelineApiService {
private async request<T = unknown>(
endpoint: string,
options?: RequestInit
): Promise<T> {
private async request<T = unknown>(endpoint: string, options?: RequestInit): Promise<T> {
const url = `${API_BASE_URL}/pipeline${endpoint}`;
const response = await fetch(url, {
@ -79,4 +72,4 @@ class PipelineApiService {
}
// Export singleton instance
export const pipelineApi = new PipelineApiService();
export const pipelineApi = new PipelineApiService();

View file

@ -32,7 +32,6 @@ export interface ProviderMappingStats {
coveragePercentage: number;
}
export type DataClearType = 'exchanges' | 'provider_mappings' | 'all';
export interface PipelineOperation {
@ -44,4 +43,4 @@ export interface PipelineOperation {
category: 'sync' | 'stats' | 'maintenance';
dangerous?: boolean;
params?: Record<string, unknown>;
}
}