import type { ProxyUserRecord } from '../../src/shared/contracts'; import { deriveDashboardSnapshot, render3proxyConfig, type ObservedRuntimeState, type RuntimePaths, type RuntimeSnapshot } from './config'; import type { StateStore } from './store'; import { readObservedTraffic } from './traffic'; export async function getDashboardSnapshot( store: StateStore, runtime: { getSnapshot(): RuntimeSnapshot }, runtimePaths: RuntimePaths, ) { const state = await store.read(); const previewConfig = render3proxyConfig(state, runtimePaths); const traffic = await readObservedTraffic(runtimePaths, state.userRecords); const observedUsers = deriveObservedUsers( state.userRecords, traffic.userBytesByName, traffic.lastSeenByName, traffic.recentUsers, ); const observed: ObservedRuntimeState = { totalBytes: traffic.totalBytes, liveConnections: traffic.liveConnections, activeUsers: traffic.activeUsers, daily: traffic.daily, userRecords: observedUsers, }; return deriveDashboardSnapshot(state, runtime.getSnapshot(), observed, previewConfig); } function deriveObservedUsers( users: ProxyUserRecord[], userBytesByName: Map, lastSeenByName: Map, recentUsers: Set, ): ProxyUserRecord[] { return users.map((user) => { const usedBytes = userBytesByName.get(user.username) ?? 0; const lastSeenAt = lastSeenByName.get(user.username) ?? null; if (user.paused) { return { ...user, lastSeenAt, usedBytes, status: 'idle', }; } if (user.quotaBytes !== null && usedBytes >= user.quotaBytes) { return { ...user, lastSeenAt, usedBytes, status: 'fail', }; } if (user.quotaBytes !== null && user.quotaBytes > 0 && usedBytes / user.quotaBytes >= 0.8) { return { ...user, lastSeenAt, usedBytes, status: recentUsers.has(user.username) ? 'live' : 'warn', }; } return { ...user, lastSeenAt, usedBytes, status: recentUsers.has(user.username) ? 'live' : 'idle', }; }); }