import { z } from "zod" export const flowHostPeerSchema = z.object({ serverId: z.number().int().positive(), name: z.string(), publicKey: z.string().min(1), allowedIps: z.array(z.string().min(1)).min(1), address: z.string().min(1), endpoint: z.string().optional(), }) export const trafficFlowSettingsDtoSchema = z.object({ enabled: z.boolean(), collectorIp: z.string().min(1), flowListenPort: z.number().int().positive(), wgListenPort: z.number().int().positive(), prefix: z.string().min(1), publicEndpoint: z.string(), hostPublicKey: z.string(), hasHostPrivateKey: z.boolean(), hubServerId: z.number().int().positive().nullable(), retentionHours: z.number().int().positive(), topN: z.number().int().positive(), mapServiceMinSharePct: z.number().min(0).max(100), lastDatagramAt: z.string().nullable(), lastExporterIp: z.string().nullable(), lastError: z.string().nullable(), packetsReceived: z.number().int().nonnegative(), listenerBound: z.boolean(), listenerAddress: z.string().nullable(), peers: z.array(flowHostPeerSchema), }) export const trafficFlowSettingsPatchSchema = z.object({ enabled: z.boolean().optional(), collectorIp: z.string().min(1).optional(), flowListenPort: z.number().int().positive().optional(), wgListenPort: z.number().int().positive().optional(), prefix: z.string().min(1).optional(), publicEndpoint: z.string().optional(), hubServerId: z.number().int().positive().nullable().optional(), retentionHours: z.number().int().positive().optional(), topN: z.number().int().positive().max(1000).optional(), mapServiceMinSharePct: z.number().min(0).max(100).optional(), }) export const trafficFlowOverlayRequestSchema = z.object({ serverId: z.union([z.string(), z.number()]), publicEndpoint: z.string().optional(), /** GRE allow-fast-path=no: inner IPFIX через CPU. По умолчанию выкл (нагрузка на CPU). */ disableGreFastPath: z.boolean().optional(), }) export const trafficFlowHostFileSchema = z.object({ id: z.string(), label: z.string(), filename: z.string(), code: z.string(), }) export const trafficFlowOverlayResultSchema = z.object({ ok: z.boolean(), serverId: z.number().int(), interfaceName: z.string(), address: z.string(), publicKey: z.string(), linuxPeerBlock: z.string(), trafficFlow: z.boolean(), steps: z.array(z.string()), hostFiles: z.array(trafficFlowHostFileSchema), }) export const flowTalkerDtoSchema = z.object({ serverId: z.string(), serverName: z.string(), src: z.string(), dst: z.string(), proto: z.number().int(), protoName: z.string(), srcPort: z.number().int(), dstPort: z.number().int(), bytes: z.number().nonnegative(), packets: z.number().nonnegative(), bps: z.number().nonnegative(), inIface: z.string(), inIfaceIndex: z.string().optional(), outIface: z.string().optional(), nextHop: z.string().optional(), application: z.string().optional(), category: z.string().optional(), service: z.string().optional(), dstCountry: z.string().optional(), dstAsn: z.number().int().optional(), clientId: z.string().optional(), clientName: z.string().optional(), clientIp: z.string().optional(), internetPeer: z.string().optional(), internetPeerPort: z.number().int().optional(), direction: z.enum(["to_client", "from_client", "transit"]).optional(), enId: z.string().optional(), enName: z.string().optional(), plane: z.string().optional(), }) export const flowStatsDtoSchema = z.object({ exportersOnline: z.number().int().nonnegative(), bytesPerMin: z.number().nonnegative(), uniqueSrc: z.number().int().nonnegative(), uniqueDst: z.number().int().nonnegative(), topProto: z.string(), talkers: z.array(flowTalkerDtoSchema), lastExporterIp: z.string().nullable().optional(), lastError: z.string().nullable().optional(), packetsReceived: z.number().int().nonnegative().optional(), lastDatagramAt: z.string().nullable().optional(), listenerBound: z.boolean().optional(), listenerAddress: z.string().nullable().optional(), }) export type FlowHostPeer = z.infer export type TrafficFlowSettingsDto = z.infer export type TrafficFlowSettingsPatch = z.infer export type TrafficFlowOverlayResult = z.infer export type TrafficFlowHostFile = z.infer export const flowBreakdownRowSchema = z.object({ id: z.string(), label: z.string(), bytes: z.number().nonnegative(), packets: z.number().nonnegative(), bps: z.number().nonnegative(), percent: z.number().nonnegative(), }) export const flowIfaceChipSchema = z.object({ name: z.string(), index: z.string(), bps: z.number().nonnegative(), }) export const flowEntityCardSchema = z.object({ id: z.string(), name: z.string(), subtitle: z.string(), site: z.string(), country: z.string(), status: z.enum(["online", "offline", "degraded"]), rxNow: z.number(), txNow: z.number(), sessions: z.number().int().nonnegative(), rxSeries: z.array(z.number()), txSeries: z.array(z.number()), bytes: z.number().nonnegative(), }) export const flowMapEdgeSchema = z.object({ fromId: z.string(), fromLabel: z.string(), fromCountry: z.string(), toCountry: z.string(), toAsn: z.number().int().nonnegative(), category: z.string(), bytes: z.number().nonnegative(), bps: z.number().nonnegative(), }) export const flowPathRowSchema = z.object({ id: z.string(), clientId: z.string(), clientName: z.string(), ifaces: z.string(), serverId: z.string(), serverName: z.string(), inIface: z.string(), outIface: z.string(), enId: z.string(), enName: z.string(), dst: z.string(), service: z.string(), category: z.string(), plane: z.string(), bytes: z.number().nonnegative(), packets: z.number().nonnegative(), bps: z.number().nonnegative(), }) export const flowAnalyticsDtoSchema = z.object({ bpsNow: z.number().nonnegative(), bytes: z.number().nonnegative(), packets: z.number().nonnegative(), conversations: z.number().int().nonnegative(), conversationsRaw: z.number().int().nonnegative().optional(), uniqueSrc: z.number().int().nonnegative(), uniqueDst: z.number().int().nonnegative(), topProto: z.string(), topCategory: z.string().optional(), rxSeries: z.array(z.number()), txSeries: z.array(z.number()), applications: z.array(flowBreakdownRowSchema), protocols: z.array(flowBreakdownRowSchema), sources: z.array(flowBreakdownRowSchema), destinations: z.array(flowBreakdownRowSchema), interfaces: z.array(flowBreakdownRowSchema), asns: z.array(flowBreakdownRowSchema).optional(), countries: z.array(flowBreakdownRowSchema).optional(), categories: z.array(flowBreakdownRowSchema).optional(), services: z.array(flowBreakdownRowSchema).optional(), mapEdges: z.array(flowMapEdgeSchema).optional(), conversationsList: z.array(flowTalkerDtoSchema), paths: z.array(flowPathRowSchema).optional(), ifaces: z.array(flowIfaceChipSchema), live: z.boolean(), dedupApplied: z.boolean().optional(), degraded: z.boolean().optional(), bytesPayload: z.number().nonnegative().optional(), bytesOverlay: z.number().nonnegative().optional(), bytesMesh: z.number().nonnegative().optional(), bytesWire: z.number().nonnegative().optional(), bpsOverlay: z.number().nonnegative().optional(), bpsWire: z.number().nonnegative().optional(), excludeMeshApplied: z.boolean().optional(), excludeOverlayApplied: z.boolean().optional(), }) export const flowExportersDtoSchema = z.object({ exporters: z.array(flowEntityCardSchema), lastExporterIp: z.string().nullable().optional(), lastError: z.string().nullable().optional(), packetsReceived: z.number().int().nonnegative().optional(), lastDatagramAt: z.string().nullable().optional(), listenerBound: z.boolean().optional(), listenerAddress: z.string().nullable().optional(), }) export const flowClientsDtoSchema = z.object({ clients: z.array(flowEntityCardSchema), }) export const flowMonthlyDtoSchema = z.object({ month: z.string(), bytes: z.number().nonnegative(), countries: z.array(flowBreakdownRowSchema), services: z.array(flowBreakdownRowSchema), asns: z.array(flowBreakdownRowSchema), }) export const flowPurgeDtoSchema = z.object({ ok: z.literal(true), deleted: z.object({ buckets: z.number().int().nonnegative(), minuteStats: z.number().int().nonnegative(), minuteDims: z.number().int().nonnegative(), dailyDims: z.number().int().nonnegative(), hourFacts: z.number().int().nonnegative().optional(), dailyFacts: z.number().int().nonnegative().optional(), }), fileBytesBefore: z.number().int().nonnegative(), fileBytesAfter: z.number().int().nonnegative(), vacuumed: z.boolean(), }) export const flowFactsRebuildDtoSchema = z.object({ ok: z.literal(true), buckets: z.number().int().nonnegative(), facts: z.number().int().nonnegative(), days: z.array(z.string()), }) export const flowMapHopKindSchema = z.enum(["gre", "wan", "iface"]) export const flowMapHopDtoSchema = z.object({ fromId: z.string(), fromLabel: z.string(), toId: z.string(), toLabel: z.string(), kind: flowMapHopKindSchema, iface: z.string().optional(), bytes: z.number().nonnegative(), bps: z.number().nonnegative(), bpsFwd: z.number().nonnegative(), bpsRev: z.number().nonnegative(), }) export const flowMapServiceDtoSchema = z.object({ id: z.string(), label: z.string(), category: z.string(), bytes: z.number().nonnegative(), bps: z.number().nonnegative(), share: z.number().min(0).max(1), }) export const flowMapServiceEdgeDtoSchema = z.object({ fromId: z.string(), toId: z.string(), bytes: z.number().nonnegative(), bps: z.number().nonnegative(), bpsFwd: z.number().nonnegative(), bpsRev: z.number().nonnegative(), clientId: z.string().optional(), clientName: z.string().optional(), clients: z.array(z.object({ id: z.string(), name: z.string(), })).optional(), }) export const flowMapServicePathDtoSchema = z.object({ clientId: z.string(), clientName: z.string(), viaId: z.string(), viaName: z.string(), enId: z.string(), enName: z.string(), serviceId: z.string(), bytes: z.number().nonnegative(), bps: z.number().nonnegative(), }) /** Сервисы внутри одной страны: id вида `cc:us|svc:google`, рёбра от `countryId`. */ export const flowMapCountryServiceGroupDtoSchema = z.object({ countryId: z.string(), services: z.array(flowMapServiceDtoSchema), edges: z.array(flowMapServiceEdgeDtoSchema), paths: z.array(flowMapServicePathDtoSchema), }) export const flowMapHopsDtoSchema = z.object({ hops: z.array(flowMapHopDtoSchema), live: z.boolean(), rangeMinutes: z.number().int().positive(), windowSec: z.number().positive(), totalBytes: z.number().nonnegative().optional(), namedBytes: z.number().nonnegative().optional(), unclassifiedBytes: z.number().nonnegative().optional(), asnLoaded: z.boolean().optional(), countryLoaded: z.boolean().optional(), services: z.array(flowMapServiceDtoSchema).optional(), serviceEdges: z.array(flowMapServiceEdgeDtoSchema).optional(), servicePaths: z.array(flowMapServicePathDtoSchema).optional(), countries: z.array(flowMapServiceDtoSchema).optional(), countryEdges: z.array(flowMapServiceEdgeDtoSchema).optional(), countryPaths: z.array(flowMapServicePathDtoSchema).optional(), countryServiceGroups: z.array(flowMapCountryServiceGroupDtoSchema).optional(), mapServiceMinSharePct: z.number().min(0).max(100).optional(), dedupApplied: z.boolean(), excludeMeshApplied: z.boolean(), excludeOverlayApplied: z.boolean(), }) export type FlowTalkerDto = z.infer export type FlowStatsDto = z.infer export type FlowBreakdownRow = z.infer export type FlowIfaceChip = z.infer export type FlowEntityCard = z.infer export type FlowMapEdge = z.infer export type FlowPathRow = z.infer export type FlowAnalyticsDto = z.infer export type FlowExportersDto = z.infer export type FlowClientsDto = z.infer export type FlowMonthlyDto = z.infer export type FlowPurgeDto = z.infer export type FlowFactsRebuildDto = z.infer export type FlowMapHopKind = z.infer export type FlowMapHop = z.infer export type FlowMapService = z.infer export type FlowMapServiceEdge = z.infer export type FlowMapServicePath = z.infer export type FlowMapCountryServiceGroup = z.infer export type FlowMapHopsDto = z.infer