import { z } from "zod" import { requestJson } from "./http-client" const count = z.number().int().nonnegative().safe() const timestamp = z.string().min(1).refine(value => Number.isFinite(Date.parse(value))).transform(value => new Date(value).toISOString()) const common = z.object({ enabled: z.boolean(), intervalSec: count.positive(), lastCollectedAt: timestamp.nullable(), lastDurationMs: count.nullable(), lastError: z.string().nullable(), collectorRunning: z.boolean().optional() }) const retained = common.extend({ retentionDays: count.positive() }) const uptime = retained.extend({ resourcesEnabled: z.boolean(), pingEnabled: z.boolean(), speedEnabled: z.boolean(), probeIntervalSec: count.positive(), speedIntervalSec: count.positive() }) async function settings(baseUrl: string, path: string, schema: z.ZodType, init?: RequestInit): Promise { const raw = await requestJson(baseUrl, path, { ...init, method: "GET", signal: AbortSignal.any([...(init?.signal ? [init.signal] : []), AbortSignal.timeout(30_000)]) }) const result = schema.safeParse(raw) if (!result.success) throw new Error("Настройки сборщика не подтверждены: получен некорректный ответ сервера") return result.data } export function getTrafficCollectorSettings(baseUrl: string, init?: RequestInit) { return settings(baseUrl, "/api/traffic/settings", retained, init) } export function getServersApiPingSettings(baseUrl: string, init?: RequestInit) { return settings(baseUrl, "/api/servers-api-ping/settings", common, init) } export function getUptimeCollectorSettings(baseUrl: string, init?: RequestInit) { // Scheduler metadata is obtained independently through the scheduler API. return settings(baseUrl, "/api/uptime/settings", uptime, init) } export function getInternetPathSettings(baseUrl: string, init?: RequestInit) { return settings(baseUrl, "/api/internet-path/settings", retained, init) } const trafficPatch = z.object({ enabled: z.boolean().optional(), intervalSec: count.min(5).optional(), retentionDays: count.positive().optional() }).strict() const restPatch = z.object({ enabled: z.boolean().optional(), intervalSec: count.min(10).optional() }).strict() const uptimePatch = z.object({ resourcesEnabled: z.boolean().optional(), pingEnabled: z.boolean().optional(), speedEnabled: z.boolean().optional(), intervalSec: count.min(5).optional(), probeIntervalSec: count.min(5).optional(), speedIntervalSec: count.min(10).optional(), retentionDays: count.positive().optional() }).strict() const internetPatch = z.object({ enabled: z.boolean().optional(), intervalSec: count.min(30).optional(), retentionDays: count.positive().optional() }).strict() async function putSettings>(baseUrl: string, path: string, payload: P, input: z.ZodType

, output: z.ZodType, init?: RequestInit): Promise { const valid = input.safeParse(payload) if (!valid.success || !Object.keys(valid.data).some(key => valid.data[key] !== undefined)) throw new Error("Укажите допустимые целые значения настроек сборщика") const body = valid.data const raw = await requestJson(baseUrl, path, { ...init, method: "PUT", body: JSON.stringify(body), signal: AbortSignal.any([...(init?.signal ? [init.signal] : []), AbortSignal.timeout(30_000)]) }) const parsed = z.object({ ok: z.literal(true), settings: output }).safeParse(raw) if (!parsed.success) throw new Error("Сохранение настроек не подтверждено. Обновите данные перед повторной попыткой") const confirmed = parsed.data.settings as Record if (Object.entries(body).some(([key, value]) => value !== undefined && confirmed[key] !== value)) throw new Error("Сервер подтвердил другие настройки. Обновите данные перед повторной попыткой") return parsed.data.settings } export function putTrafficCollectorSettings(baseUrl: string, payload: z.infer, init?: RequestInit) { return putSettings(baseUrl, "/api/traffic/settings", payload, trafficPatch, retained, init) } export function putServersApiPingSettings(baseUrl: string, payload: z.infer, init?: RequestInit) { return putSettings(baseUrl, "/api/servers-api-ping/settings", payload, restPatch, common, init) } export function putUptimeCollectorSettings(baseUrl: string, payload: z.infer, init?: RequestInit) { return putSettings(baseUrl, "/api/uptime/settings", payload, uptimePatch, uptime, init) } export function putInternetPathSettings(baseUrl: string, payload: z.infer, init?: RequestInit) { return putSettings(baseUrl, "/api/internet-path/settings", payload, internetPatch, retained, init) }