15 lines
1.4 KiB
TypeScript
15 lines
1.4 KiB
TypeScript
import {z} from "zod"
|
|
const rate=z.number().finite().nonnegative()
|
|
const row=z.object({id:z.string().trim().min(1),rxNow:rate,txNow:rate,rxSeries:z.array(rate),txSeries:z.array(rate)})
|
|
const payload=z.object({servers:z.array(row)}).refine(data=>new Set(data.servers.map(r=>r.id)).size===data.servers.length&&data.servers.every(r=>r.rxSeries.length===r.txSeries.length&&r.rxSeries.length===data.servers[0].rxSeries.length))
|
|
export interface DashboardTraffic {rx:number[];tx:number[];rxNow:number;txNow:number}
|
|
/** API series share an index axis; unequal series cannot be completed with assumed zero. */
|
|
export function parseDashboardTraffic(raw:unknown):DashboardTraffic {
|
|
const parsed=payload.safeParse(raw)
|
|
if(!parsed.success)throw Error("Некорректные данные трафика: проверьте счётчики и согласованность серий")
|
|
const rows=parsed.data.servers,length=rows[0]?.rxSeries.length??0
|
|
const total={rx:Array.from({length},(_,i)=>rows.reduce((sum,r)=>sum+r.rxSeries[i],0)),tx:Array.from({length},(_,i)=>rows.reduce((sum,r)=>sum+r.txSeries[i],0)),rxNow:rows.reduce((sum,r)=>sum+r.rxNow,0),txNow:rows.reduce((sum,r)=>sum+r.txNow,0)}
|
|
if(![total.rxNow,total.txNow,...total.rx,...total.tx].every(Number.isFinite))throw Error("Суммарный трафик превышает допустимый диапазон")
|
|
return total
|
|
}
|