Commit graph

5 commits

Author SHA1 Message Date
MHSanaei
e0e6200e2f
feat(clients): server-side bulk create/delete with per-inbound batching
Replace the panel-side fan-out (Promise.all of single /add and /del
calls) that raced on the shared inbound config and capped throughput at
roughly one round-trip per client. New endpoints batch the work on the
server:

- POST /panel/api/clients/bulkDel  { emails, keepTraffic }
- POST /panel/api/clients/bulkCreate  [ {client, inboundIds}, ... ]

BulkDelete groups emails by inbound and performs a single
read-modify-write per inbound (one JSON parse, one marshal, one Save)
instead of N. Per-row DB cleanups (ClientInbound, ClientTraffic,
InboundClientIps, ClientRecord) are batched with WHERE...IN queries.
Per-email failures are reported via Skipped[] and processing continues.

BulkCreate iterates payloads sequentially through the same Create path
single-add uses, so heterogeneous batches (different inboundIds, plans)
remain valid in one round-trip.

Frontend bulkDelete/bulkCreate hooks parse the new response shape
({ deleted|created, skipped[] }) and the bulk-add modal now posts a
single request instead of fanning out emails.
2026-05-27 00:20:52 +02:00
MHSanaei
a3012daa8f
feat(frontend): migrate five secondary form modals to Zod schemas
Apply the schema + safeParse-on-submit pattern (introduced for
ClientFormModal / ClientBulkAddModal) to five more forms:

- ClientBulkAdjustModal: ClientBulkAdjustFormSchema enforces 'at least
  one of addDays / addGB is non-zero' via .refine(), replacing the
  ad-hoc days+gb check.
- BalancerFormModal: BalancerFormSchema covers tag and selector
  required-ness; the duplicate-tag check stays inline since it needs
  the otherTags prop. Per-field validateStatus now reads from the
  parsed issues map.
- RuleFormModal: RuleFormSchema captures the form shape (no required
  fields - every property is optional by design). safeParse short-
  circuits if anything is structurally wrong.
- CustomGeoFormModal: CustomGeoFormSchema folds the regex alias rule
  and the http(s) URL validation (including URL parse) into the
  schema, replacing a 20-line validate() function.
- TwoFactorModal: TotpCodeSchema (z.string().regex(/^\d{6}$/)) drives
  both the disabled-state of the OK button and the safeParse gate
  before the TOTP comparison.

Schemas live alongside the matching API schemas:
- ClientBulkAdjustFormSchema in schemas/client.ts
- BalancerFormSchema / RuleFormSchema / CustomGeoFormSchema in schemas/xray.ts
- TotpCodeSchema in schemas/login.ts (next to LoginFormSchema)

No UX change for valid inputs.
2026-05-25 17:45:02 +02:00
MHSanaei
6bbc9f6769
feat(frontend): drive form validation from Zod schemas
NodeFormModal — full conversion to AntD Form.useForm with antdRule
on every required field. Inline field errors replace the single
'fillRequired' toast. testConnection now runs validateFields(['address','port'])
before sending.

ClientFormModal and ClientBulkAddModal — minimal conversion: keep the
existing useState-driven controlled-component pattern, but replace the
hand-rolled `if (!form.x)` checks with schema.safeParse(form). The
schema is the single source of truth for required-ness and types;
ClientCreateFormSchema layers on the create-only `inboundIds.min(1)` rule.

New schemas (in src/schemas/):
  NodeFormSchema (node.ts)
  ClientFormSchema / ClientCreateFormSchema (client.ts)
  ClientBulkAddFormSchema (client.ts)

Other 16+ form modals stay on the current pattern — the antdRule adapter
ships from the first Zod pass for opportunistic migration as forms are
touched.
2026-05-25 16:41:56 +02:00
MHSanaei
c16fb93899
fix(frontend): allow null slices in client/summary schemas
Go's encoding/json emits nil []T as null, not []. The initial
ClientPageResponseSchema and ClientHydrateSchema rejected null
inboundIds / summary.online / summary.depleted / etc., causing
[zod] warnings on every empty list.

Add nullableStringArray / nullableNumberArray helpers that accept
null and transform to [] so consuming code keeps seeing arrays.
Mark ClientRecord.traffic and .reverse nullable too (reverse is
explicitly null in MarshalJSON when storage is empty).
2026-05-25 16:30:48 +02:00
MHSanaei
d00ddc3f58
feat(frontend): extend Zod validation to remaining query/mutation hooks
Adds Zod schemas for client/inbound/xray/node-probe endpoints and wires
useNodeMutations, useClients, useInbounds, useXraySetting, useDatepicker
through parseMsg. Drops the duplicated per-file ApiMsg<T> interfaces and
the local ClientRecord / OutboundTrafficRow / XraySettingsValue / DefaultsPayload
declarations in favour of schema-inferred types re-exported from the
new src/schemas/ modules.

API boundary now validates: clients list/paged, clients onlines,
clients lastOnline, clients get/hydrate, inbounds slim, inbounds get,
inbounds options, defaultSettings, xray config, xray outbounds traffic,
xray testOutbound, xray getXrayResult, getDefaultJsonConfig, nodes probe,
nodes test. Mutation responses that consume obj (bulkAdjust, delDepleted,
nodes probe / test) get response validation; pass-through mutations stay
agnostic. NodeFormModal type-aligned to Msg<ProbeResult>.
2026-05-25 16:14:00 +02:00