import { z } from "zod" const serverId = z.number().int().positive().safe() const time = z.string().datetime({ offset: true }) export const containerStateRowSchema = z.object({ id: z.string().min(1), rosId: z.string().min(1), name: z.string().min(1), serverId: z.string().regex(/^[1-9]\d*$/), image: z.string(), tag: z.string(), status: z.enum(["running", "stopped", "error", "unknown"]), envs: z.array(z.object({ key: z.string().min(1), value: z.string() })), mounts: z.array(z.object({ dst: z.string().min(1), src: z.string().optional() })), interfaces: z.array(z.string().min(1)), cmd: z.string().optional(), startOnBoot: z.boolean().nullable(), comment: z.string(), uptime: z.string().optional(), cpu: z.number().finite().min(0).max(100).optional(), memMb: z.number().finite().nonnegative().optional(), }) export const containerServerStateSchema = z.object({ serverId, collectedAt: time, availability: z.enum(["available", "unsupported", "error"]), containers: z.array(containerStateRowSchema), failures: z.array(z.object({ resource: z.enum(["containers", "envs", "mounts"]), error: z.string().min(1) })), }).superRefine((value, ctx) => { const ids = new Set() for (const row of value.containers) { if (row.serverId !== String(value.serverId) || row.id !== value.serverId + "-" + row.rosId || ids.has(row.rosId)) ctx.addIssue({ code: "custom", message: "Контейнеры не соответствуют устройству или содержат дубли" }) ids.add(row.rosId) } const resources = value.failures.map(f => f.resource) if (new Set(resources).size !== resources.length) ctx.addIssue({ code: "custom", message: "Дубли ошибок ресурсов" }) if (value.availability !== "available" && value.containers.length) ctx.addIssue({ code: "custom", message: "Неуспешная загрузка содержит контейнеры" }) if (value.availability === "error" && !resources.includes("containers") || value.availability === "available" && resources.includes("containers") || value.availability === "unsupported" && resources.length) ctx.addIssue({ code: "custom", message: "Состояние не соответствует ошибкам" }) }) export const containersStateSchema = z.object({ collectedAt: time, servers: z.array(containerServerStateSchema), }).superRefine((value, ctx) => { if (new Set(value.servers.map(s => s.serverId)).size !== value.servers.length) ctx.addIssue({ code: "custom", message: "Дубли устройств" }) }) export type ContainerStateRow = z.infer export type ContainerServerState = z.infer export type ContainersState = z.infer