import * as plugins from '../plugins.js'; import * as interfaces from '../../ts_interfaces/index.js'; import { appState } from './shared.js'; import { getActionContext } from './login.js'; export interface IStatsState { serverStats: interfaces.data.IServerStats | null; emailStats: interfaces.data.IEmailStats | null; dnsStats: interfaces.data.IDnsStats | null; securityMetrics: interfaces.data.ISecurityMetrics | null; radiusStats: interfaces.data.IRadiusStats | null; vpnStats: interfaces.data.IVpnStats | null; lastUpdated: number; isLoading: boolean; error: string | null; } export const statsStatePart = await appState.getStatePart( 'stats', { serverStats: null, emailStats: null, dnsStats: null, securityMetrics: null, radiusStats: null, vpnStats: null, lastUpdated: 0, isLoading: false, error: null, }, 'soft' // Stats are cached but not persisted ); // Fetch All Stats Action - Using combined endpoint for efficiency export const fetchAllStatsAction = statsStatePart.createAction(async (statePartArg): Promise => { const context = getActionContext(); const currentState = statePartArg.getState()!; if (!context.identity) return currentState; try { // Use combined metrics endpoint - single request instead of 4 const combinedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest< interfaces.requests.IReq_GetCombinedMetrics >('/typedrequest', 'getCombinedMetrics'); const combinedResponse = await combinedRequest.fire({ identity: context.identity, sections: { server: true, email: true, dns: true, security: true, network: false, // Network is fetched separately for the network view radius: true, vpn: true, }, }); // Update state with all stats from combined response return { serverStats: combinedResponse.metrics.server || currentState.serverStats, emailStats: combinedResponse.metrics.email || currentState.emailStats, dnsStats: combinedResponse.metrics.dns || currentState.dnsStats, securityMetrics: combinedResponse.metrics.security || currentState.securityMetrics, radiusStats: combinedResponse.metrics.radius || currentState.radiusStats, vpnStats: combinedResponse.metrics.vpn || currentState.vpnStats, lastUpdated: Date.now(), isLoading: false, error: null, }; } catch (error: unknown) { return { ...currentState, isLoading: false, error: (error as Error).message || 'Failed to fetch statistics', }; } });