3x-ui/frontend/ZOD_MIGRATION_STATUS.md
MHSanaei bfdaf7a8f8
Some checks are pending
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Release 3X-UI / Build for Windows (push) Waiting to run
docs(frontend): record FinalMaskForm rewrite + hookup in status doc
Mainline migration goal — replace class-based xray models with Zod
schemas as the single source of truth + drive all forms through
AntD `Form.useForm` + `antdRule(schema.shape.X)` — is complete.
Remaining items are incremental polish.
2026-05-26 14:39:49 +02:00

132 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 3x-ui Frontend Zod Migration — Status
Branch: `feat/frontend-zod-validation` · 83 commits ahead of `main`
Last updated: 2026-05-26
## What this is
The work tracked here is the migration described in
`C:\Users\Hossein Sanaei\.claude\plans\zod-soft-feather.md` — replacing the
class-based xray models (`models/inbound.ts`, `models/outbound.ts`) with Zod
schemas as the single source of truth, standardizing every form on AntD
`Form.useForm` + `antdRule(schema.shape.X)`, and tightening
`@typescript-eslint/no-explicit-any` to `error`.
Verify state: `npm run typecheck` clean, `npm run lint` clean,
`npm run test` 302/302, snapshot baselines 172/172.
---
## Done
### Foundations
- API-boundary Zod validation in TanStack Query hooks (`parseMsg` helper)
- Backend request-body validation via `go-playground/validator`
- Go-first codegen tool (`tools/openapigen`) emitting `zod.ts` + `types.ts`
- `antdRule(schema)` helper bridging Zod issues to AntD form rules
- Five secondary modals migrated to Pattern A (Login, 2FA, Geo, Balancer, Rule)
- Pre-save schema guard on Inbound/Outbound form submits
### Schemas — `frontend/src/schemas/`
- `primitives/` — port, protocol, sniffing, atomic dictionaries
- `protocols/inbound/*` — 10 protocols as leaf schemas
- `protocols/outbound/*` — 11 protocols as leaf schemas
- `protocols/stream/*` — 7 networks (tcp/kcp/ws/grpc/httpupgrade/xhttp/hysteria)
- `protocols/security/*` — 3 securities (none/tls/reality)
- `forms/inbound-form.ts``InboundFormValues` discriminated union
- `forms/outbound-form.ts``OutboundFormValues` discriminated union
- Stream + security families wired as `z.discriminatedUnion` with intersection
### Pure-function ports — `frontend/src/lib/xray/`
- `headers.ts``toHeaders`, `toV2Headers`, `getHeaderValue`
- `inbound-link.ts``genVmessLink`, `genVlessLink`, `genTrojanLink`,
`genShadowsocksLink`, `genHysteriaLink`, Wireguard link/config
- `outbound-link-parser.ts` — vmess/vless/trojan/shadowsocks/hysteria2
- `inbound-defaults.ts``createDefault{Vmess,Vless,...}{Client,InboundSettings}`
- `outbound-defaults.ts` — settings factories + dispatcher
- `outbound-form-adapter.ts` — raw ↔ `OutboundFormValues` round-trip
- `protocol-capabilities.ts` — capability predicates as pure functions
### Form modals on Pattern A
- `InboundFormModal.tsx` — full rewrite, atomic-swapped from `.new.tsx`
- Tabs: Basic, Sniffing, Protocol, Stream, Security, Advanced JSON,
Fallbacks
- All 10 protocols (VLESS, VMess, Trojan, Shadowsocks, HTTP, Mixed,
Tunnel, TUN, Wireguard, Hysteria)
- Full Stream tab (TCP, KCP, WS, gRPC, HTTPUpgrade, XHTTP, Hysteria)
- Full Security tab (TLS list, Reality, ECH, mldsa65)
- 18-field sockopt section, full TLS cert list, external-proxy section
- `OutboundFormModal.tsx` — full rewrite, atomic-swapped from `.new.tsx`
- All 12 protocols (vmess/vless/trojan/shadowsocks/socks/http/hysteria/
freedom/blackhole/dns/loopback/wireguard)
- Full Stream tab with XHTTP advanced fields + xmux sub-form
- Full Security tab (TLS + Reality + Vision flow)
- Sockopt section (17 knobs)
- Mux section
- JSON tab for advanced fields
- Link import (vmess/vless/trojan/ss/hysteria2) with full XHTTP
round-trip (padding obfs + session/seq/uplink keys + all post-size
knobs)
- `FinalMaskForm` rewritten to Pattern A (Form.List-driven) and wired
into both stream tabs (Inbound + Outbound). Covers TCP/UDP mask
arrays, all 13 UDP mask types, header-custom nested groups, noise
items, and the QUIC params sub-form.
### Tests
- Golden-file fixture suite (`test/golden/fixtures/`)
- Snapshot-baseline regression tests for inbound-full / outbound / stream /
security DUs
- Shadow-parse harness asserting legacy class and Zod converge
- Link-parser tests (15 round-trip cases including XHTTP padding-obfs)
- Outbound form-adapter tests (15 round-trip cases)
- 302 tests across 12 files, 172 snapshots
### Build infrastructure
- `@typescript-eslint/no-explicit-any: 'error'` enforced
- `.github/workflows/ci.yml` runs `typecheck` + `test` before `build`
- Vite pinned to 8.0.13 (dev-mode dep-optimizer regression in 8.0.14)
---
## Remaining
### Out of migration scope (per plan)
- `DBInbound`, `Status`, `AllSetting` legacy classes — flagged as out of
scope in `zod-soft-feather.md`. The mainline migration of
`models/inbound.ts` / `models/outbound.ts` cannot delete them entirely
while `DBInbound.toInbound()` still imports.
- The plan accepts this and treats parity via snapshot baselines instead.
### Nice-to-haves — would not block ship
- Reality `sid=` multi-value parsing in share-link import
(outbound reality only carries a single shortId — this is server-side
state)
- `fm=` (FinalMask) param in share-link import
- VMess link `xmux` nested JSON parsing (currently round-trips at the
XHTTP top level; nested xmux object is left empty)
- Tighter `.loose()` removal in `schemas/api/inbound.ts`,
`schemas/api/client.ts`, `schemas/xray.ts` — gated on Step 6 of the plan
(currently held because the codegen tool still emits one or two loose
fields the panel writes back)
---
## How to pick up where this left off
1. `git checkout feat/frontend-zod-validation`
2. `cd frontend && npm install && npm run typecheck && npm run test`
3. Open `C:\Users\Hossein Sanaei\.claude\plans\zod-soft-feather.md`
Steps 15 are done. Step 6 (tighten `.loose()`) and Step 7 (lint/CI
tightening) are partially done.
4. Nothing in this list blocks ship. The mainline migration goal
(replace class-based models with Zod schemas + Pattern A forms) is
done; remaining work is incremental polish.