28 lines
1.6 KiB
TypeScript
28 lines
1.6 KiB
TypeScript
import { z } from "zod"
|
|
import { isIP } from "node:net"
|
|
const destination = z.string().trim().refine(value => {
|
|
const [address, prefix, extra] = value.split("/")
|
|
return extra === undefined && isIP(address ?? "") === 4 && (prefix === undefined || /^\d+$/.test(prefix) && Number(prefix) <= 32)
|
|
}, "Нужен IPv4 адрес или префикс")
|
|
const gateway = z.string().trim().refine(value => {
|
|
const [address, iface, extra] = value.split("%")
|
|
return extra === undefined && isIP(address ?? "") === 4 && (iface === undefined || Boolean(iface) && !/\s/.test(iface))
|
|
}, "Нужен IPv4 шлюз с необязательным интерфейсом")
|
|
const serverId = z.union([z.number().int().positive(), z.string().trim().regex(/^\d+$/)])
|
|
.transform(Number).refine(value => Number.isSafeInteger(value) && value > 0)
|
|
export const recursiveTargetSchema = z.object({ serverId })
|
|
export const recursiveInputRowSchema = z.object({
|
|
id: z.string().optional().default(""),
|
|
dstAddress: destination, gateway,
|
|
distance: z.number().int().min(0).max(255),
|
|
scope: z.number().int().min(0).max(255).nullable(),
|
|
targetScope: z.number().int().min(0).max(255).nullable(),
|
|
routingTable: z.string().trim().min(1), checkGateway: z.enum(["none", "arp", "ping", "bfd"]),
|
|
country: z.string(), comment: z.string(), disabled: z.boolean(),
|
|
})
|
|
export const recursiveInputRowsSchema = z.array(recursiveInputRowSchema)
|
|
.refine(rows => { const ids = rows.map(row => row.id).filter(Boolean); return new Set(ids).size === ids.length })
|
|
export const recursiveApplyBodySchema = recursiveTargetSchema.extend({
|
|
routes: recursiveInputRowsSchema, source: z.enum(["apply", "copy"]).optional(),
|
|
})
|