3x-ui/frontend/src/pages/xray
MHSanaei 0208396802
feat(frontend): migrate DNS + Routing to Zod, align with xray docs
Adds first-class Zod schemas for the xray-core DNS block and routing
sub-objects (Balancer, Rule) matching the documented shape at
https://xtls.github.io/config/dns.html and
https://xtls.github.io/config/routing.html, then wires the
DnsServerModal and BalancerFormModal up to those schemas.

schemas/dns.ts (new):
- DnsQueryStrategySchema enum (UseIP/UseIPv4/UseIPv6/UseSystem)
- DnsHostsSchema record(string -> string | string[])
- DnsServerObjectInnerSchema + DnsServerObjectSchema (with preprocess
  to migrate legacy `expectIPs` -> `expectedIPs` alias)
- DnsServerEntrySchema = string | DnsServerObject (xray accepts both)
- DnsObjectSchema with all documented fields and defaults

schemas/routing.ts (new):
- RuleProtocolSchema enum (http/tls/quic/bittorrent)
- RuleWebhookSchema (url/deduplication/headers)
- RuleObjectSchema covering every documented field (domain/ip/port/
  sourcePort/localPort/network/sourceIP/localIP/user/vlessRoute/
  inboundTag/protocol/attrs/process/outboundTag/balancerTag/ruleTag/
  webhook) with type=literal('field').default('field')
- BalancerStrategyTypeSchema enum (random/roundRobin/leastPing/leastLoad)
- BalancerCostObjectSchema {regexp,match,value}
- BalancerStrategySettingsSchema (expected/maxRTT/tolerance/baselines/costs)
- BalancerStrategySchema + BalancerObjectSchema

schemas/xray.ts:
- routing.rules: was loose 3-field object, now z.array(RuleObjectSchema)
- routing.balancers: was z.array(z.unknown()), now z.array(BalancerObjectSchema)
- dns: was 2-field loose, now full DnsObjectSchema
- BalancerFormSchema: strategy now BalancerStrategyTypeSchema (enum)
  instead of z.string(); fallbackTag defaults to ''; settings? added
  for leastLoad

DnsServerModal (full Pattern A rewrite):
- useState/DnsForm interface -> Form.useForm<DnsServerForm>()
- manual domain/expectedIP/unexpectedIP list -> Form.List
- antdRule on address/port/timeoutMs for inline validation
- preserves legacy collapse-to-bare-string behavior on submit

BalancerFormModal:
- Adds conditional leastLoad sub-form (Expected/MaxRTT/Tolerance/
  Baselines/Costs) wired to BalancerStrategySettingsSchema
- Strategy options derived from schema enum
- Cost rows with regexp/literal switch + match + value
- required prop on Tag and Selector for red asterisk visual

BalancersTab:
- BalancerRecord interface -> type alias to BalancerObject
- onConfirm now propagates strategy.settings to wire when leastLoad
- Removes useMemo wrapping `columns` array. The memo had deps
  [t, isMobile] (with an eslint-disable) so the column render
  functions kept their original closure over `openEdit`. Once a
  balancer was created and the user clicked the edit button, the
  stale openEdit fired with empty `rows`, so rows[idx] was undefined
  and the modal opened blank. Columns are cheap to rebuild each
  render, so dropping the memo is the right fix.

DnsTab + RoutingTab: switch ad-hoc interfaces to schema-derived types.

translations (en-US, fa-IR): add the previously-missing
pages.xray.balancerTagRequired and pages.xray.balancerSelectorRequired
keys so antdRule surfaces a real message instead of the raw i18n key.
2026-05-26 23:36:01 +02:00
..
BalancerFormModal.tsx feat(frontend): migrate DNS + Routing to Zod, align with xray docs 2026-05-26 23:36:01 +02:00
BalancersTab.tsx feat(frontend): migrate DNS + Routing to Zod, align with xray docs 2026-05-26 23:36:01 +02:00
BasicsTab.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
BasicsTab.tsx refactor(frontend): lift OutboundProtocols + OutboundDomainStrategies to schemas/primitives 2026-05-26 01:07:02 +02:00
DnsPresetsModal.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
DnsPresetsModal.tsx Frontend rewrite: React + TypeScript with AntD v6 (#4498) 2026-05-23 15:21:45 +02:00
DnsServerModal.tsx feat(frontend): migrate DNS + Routing to Zod, align with xray docs 2026-05-26 23:36:01 +02:00
DnsTab.css Frontend rewrite: React + TypeScript with AntD v6 (#4498) 2026-05-23 15:21:45 +02:00
DnsTab.tsx feat(frontend): migrate DNS + Routing to Zod, align with xray docs 2026-05-26 23:36:01 +02:00
NordModal.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
NordModal.tsx refactor(frontend): tighten HttpUtil generics from any to unknown 2026-05-25 19:51:39 +02:00
OutboundFormModal.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
OutboundFormModal.tsx feat(frontend): align finalmask + sockopt with xray docs, add golden fixtures 2026-05-26 22:14:38 +02:00
OutboundsTab.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
OutboundsTab.tsx refactor(frontend): lift OutboundProtocols + OutboundDomainStrategies to schemas/primitives 2026-05-26 01:07:02 +02:00
RoutingTab.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
RoutingTab.tsx feat(frontend): migrate DNS + Routing to Zod, align with xray docs 2026-05-26 23:36:01 +02:00
RuleFormModal.tsx feat(frontend): migrate five secondary form modals to Zod schemas 2026-05-25 17:45:02 +02:00
WarpModal.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
WarpModal.tsx refactor(frontend): tighten HttpUtil generics from any to unknown 2026-05-25 19:51:39 +02:00
XrayPage.css Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
XrayPage.tsx Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00