3x-ui/frontend/src/schemas/protocols/outbound/trojan.ts
MHSanaei 8d45cd8c68
feat(frontend): protocol-leaf Zod schemas with discriminated unions
Stand up schemas/primitives (Port, Flow, Protocol, Sniffing) and per-protocol
leaf schemas for all 10 inbound and 13 outbound xray protocols. The leaves
omit any inner `protocol` literal — the discriminator lives at the parent
level so consumers narrow on `.protocol` without redundant projection. Wire
shape is preserved per protocol: vmess outbound stays in `vnext[]`, trojan
and shadowsocks outbound in `servers[]`, vless outbound flat, http/socks
outbound in `servers[].users[]`.

Cross-protocol atoms (port, flow, sniffing dest, protocol enum) live in
primitives. Protocol-specific enums (vmess security, ss method/network,
hysteria version, freedom domain strategy, dns rule action) stay with their
leaves. Tagged-wrapper `z.discriminatedUnion('protocol', [...])` composes
both InboundSettingsSchema and OutboundSettingsSchema; existing class-based
models in src/models/ are untouched and will be retired in Step 3 once the
golden-file safety net is in place.
2026-05-25 23:02:08 +02:00

18 lines
705 B
TypeScript

import { z } from 'zod';
import { PortSchema } from '@/schemas/primitives';
// Trojan outbound persists as { servers: [{ address, port, password }] }
// — distinct from VLESS outbound which stores the connect target flat at
// the settings root. The wrapping mirrors what Xray expects.
export const TrojanOutboundServerSchema = z.object({
address: z.string().min(1),
port: PortSchema,
password: z.string().min(1),
});
export type TrojanOutboundServer = z.infer<typeof TrojanOutboundServerSchema>;
export const TrojanOutboundSettingsSchema = z.object({
servers: z.array(TrojanOutboundServerSchema).min(1),
});
export type TrojanOutboundSettings = z.infer<typeof TrojanOutboundSettingsSchema>;