Files
MikrotikManager/shared/api/traffic-flow.ts
T
DenozordecandCursor 6332d83a12
Docker images / prepare-release (push) Successful in 10s
Docker images / backend-image (push) Successful in 2m14s
Docker images / frontend-image (push) Successful in 3m14s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 46s
Docker images / publish-release (push) Successful in 11s
feat(traffic): показать поток NetFlow на карте сети
Скорость между узлами считается как в Трафике (5 мин, без overlay/mesh), отдельно от ёмкости WAN и BT.

Co-authored-by: Cursor <[email protected]>
2026-09-07 12:37:47 +07:00

145 lines
4.5 KiB
TypeScript

import type {
FlowAnalyticsDto,
FlowClientsDto,
FlowExportersDto,
FlowMapHopsDto,
FlowMonthlyDto,
FlowPurgeDto,
FlowStatsDto,
TrafficFlowHostFile,
TrafficFlowOverlayResult,
TrafficFlowSettingsDto,
TrafficFlowSettingsPatch,
} from "@mmapp/contracts/traffic-flow"
import { requestJson } from "@/shared/api/http-client"
export type { TrafficFlowHostFile }
export async function getTrafficFlowSettings(baseUrl: string): Promise<TrafficFlowSettingsDto> {
return requestJson<TrafficFlowSettingsDto>(baseUrl, "/api/traffic/flow/settings")
}
export async function putTrafficFlowSettings(
baseUrl: string,
patch: TrafficFlowSettingsPatch,
): Promise<{ ok: boolean; settings: TrafficFlowSettingsDto }> {
return requestJson(baseUrl, "/api/traffic/flow/settings", {
method: "PUT",
body: JSON.stringify(patch),
})
}
export async function generateTrafficFlowKeys(baseUrl: string): Promise<{
ok: boolean
created: boolean
publicKey: string
settings: TrafficFlowSettingsDto
}> {
return requestJson(baseUrl, "/api/traffic/flow/settings/generate-keys", { method: "POST" })
}
export async function getTrafficFlowHostFiles(baseUrl: string): Promise<{ files: TrafficFlowHostFile[] }> {
return requestJson(baseUrl, "/api/traffic/flow/host-files")
}
export async function applyTrafficFlowOverlay(
baseUrl: string,
serverId: string | number,
publicEndpoint?: string,
): Promise<TrafficFlowOverlayResult> {
return requestJson(baseUrl, "/api/traffic/flow-overlay", {
method: "POST",
body: JSON.stringify({ serverId, publicEndpoint }),
})
}
export async function getTrafficFlows(baseUrl: string, range = "5m"): Promise<FlowStatsDto> {
return requestJson<FlowStatsDto>(baseUrl, `/api/traffic/flows?range=${encodeURIComponent(range)}`)
}
function flowQuery(params: {
range?: string
serverId?: string
userId?: string
iface?: string
dedup?: boolean
excludeMesh?: boolean
excludeOverlay?: boolean
}): string {
const q = new URLSearchParams()
if (params.range) q.set("range", params.range)
if (params.serverId) q.set("serverId", params.serverId)
if (params.userId) q.set("userId", params.userId)
if (params.iface && params.iface !== "__all__") q.set("iface", params.iface)
if (params.dedup === false) q.set("dedup", "0")
else if (params.dedup === true) q.set("dedup", "1")
if (params.excludeMesh === false) q.set("excludeMesh", "0")
else if (params.excludeMesh === true) q.set("excludeMesh", "1")
if (params.excludeOverlay === false) q.set("excludeOverlay", "0")
else if (params.excludeOverlay === true) q.set("excludeOverlay", "1")
const s = q.toString()
return s ? `?${s}` : ""
}
export async function getFlowExporters(baseUrl: string, range = "5m"): Promise<FlowExportersDto> {
return requestJson<FlowExportersDto>(baseUrl, `/api/traffic/flow/exporters?range=${encodeURIComponent(range)}`)
}
export async function getFlowClients(baseUrl: string, range = "5m"): Promise<FlowClientsDto> {
return requestJson<FlowClientsDto>(baseUrl, `/api/traffic/flow/clients?range=${encodeURIComponent(range)}`)
}
export async function getFlowMapHops(
baseUrl: string,
params: {
range?: string
serverId?: string
userId?: string
iface?: string
dedup?: boolean
excludeMesh?: boolean
excludeOverlay?: boolean
} = {},
): Promise<FlowMapHopsDto> {
return requestJson<FlowMapHopsDto>(baseUrl, `/api/traffic/flow/map-hops${flowQuery({
range: params.range ?? "5m",
serverId: params.serverId,
userId: params.userId,
iface: params.iface,
dedup: params.dedup,
excludeMesh: params.excludeMesh,
excludeOverlay: params.excludeOverlay,
})}`)
}
export async function getFlowAnalytics(
baseUrl: string,
params: {
range?: string
serverId?: string
userId?: string
iface?: string
dedup?: boolean
excludeMesh?: boolean
excludeOverlay?: boolean
},
): Promise<FlowAnalyticsDto> {
return requestJson<FlowAnalyticsDto>(baseUrl, `/api/traffic/flow/analytics${flowQuery(params)}`)
}
export async function getFlowMonthly(
baseUrl: string,
params: { month: string; serverId?: string },
): Promise<FlowMonthlyDto> {
const q = new URLSearchParams()
q.set("month", params.month)
if (params.serverId) q.set("serverId", params.serverId)
return requestJson<FlowMonthlyDto>(baseUrl, `/api/traffic/flow/monthly?${q.toString()}`)
}
export async function purgeTrafficFlowData(baseUrl: string): Promise<FlowPurgeDto> {
return requestJson<FlowPurgeDto>(baseUrl, "/api/traffic/flow/purge", { method: "POST" })
}
export { flowQuery }