import { apiRequest } from '@/lib/api' import { timeseriesSearch, type TimeseriesRequest } from './timeseries' const MAX_CSV_BYTES = 2 * 1024 * 1024 /** Uses the same authorization, HTTP errors and bounded request as JSON. A * bearer token never appears in an export URL or download filename. */ export async function fetchStatsCsv(request: TimeseriesRequest, signal?: AbortSignal): Promise { const search = timeseriesSearch(request) const response = await apiRequest(`/api/v1/stats/timeseries.csv?${search}`, { signal, headers: { Accept: 'text/csv' } }) if (!response.headers.get('Content-Type')?.toLowerCase().includes('text/csv')) throw new Error('Сервер не вернул CSV') if (Number(response.headers.get('Content-Length')) > MAX_CSV_BYTES) throw new Error('CSV превышает допустимый размер') const blob = await response.blob() if (blob.size > MAX_CSV_BYTES) throw new Error('CSV превышает допустимый размер') return blob } export function saveStatsCsv(blob: Blob, request: TimeseriesRequest) { const url = URL.createObjectURL(blob) const anchor = document.createElement('a') anchor.href = url anchor.download = `evofw-packets-${request.resolution}-${request.from.slice(0, 10)}-${request.to.slice(0, 10)}.csv` document.body.appendChild(anchor) anchor.click() anchor.remove() window.setTimeout(() => URL.revokeObjectURL(url), 1000) }