From bd03f1a1172b0d96855640d45d34f7f40766633b Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Tue, 26 May 2026 00:37:18 +0200 Subject: [PATCH] refactor(frontend): swap InboundsPage clone fallback off Inbound.Settings.getSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First Step 4 call-site swap. createDefaultInboundSettings(protocol) lands in lib/xray/inbound-defaults — a protocol-aware dispatch over the 10 per-protocol settings factories already in this module. Returns a Zod- parsable plain object instead of a class instance, so callers that just need the wire-shape JSON can drop the class hierarchy without touching the broader form modals. InboundsPage's clone path used Inbound.Settings.getSettings(p).toString() as the fallback when settings JSON parsing failed. That's now createDefaultInboundSettings + JSON.stringify, with a final '{}' guard for unknown protocols (legacy returned null and .toString() crashed — we just emit empty settings instead). The Inbound import on this file is now unused and removed. The 2 remaining getSettings call sites in InboundFormModal aren't safe to swap in isolation — the form mutates the returned class instance through methods like .addClient() and .toJson() across ~2000 lines of JSX. Those land with the full Pattern A rewrite of InboundFormModal, which the plan budgets at multiple days on its own. Suite: 89 tests across 8 files; typecheck + lint clean. --- frontend/src/lib/xray/inbound-defaults.ts | 33 ++++++++++++++++++++ frontend/src/pages/inbounds/InboundsPage.tsx | 5 +-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/xray/inbound-defaults.ts b/frontend/src/lib/xray/inbound-defaults.ts index 00b1b72d..d658373f 100644 --- a/frontend/src/lib/xray/inbound-defaults.ts +++ b/frontend/src/lib/xray/inbound-defaults.ts @@ -225,3 +225,36 @@ export function createDefaultWireguardInboundSettings( noKernelTun: seed.noKernelTun ?? false, }; } + +// Protocol-aware dispatch over every inbound-settings factory. Mirrors +// the legacy `Inbound.Settings.getSettings(protocol)` dispatcher, but +// returns a plain Zod-parsable object instead of a class instance. +// Callers swapping off the class hierarchy use this in place of +// `getSettings(p)` + `.toJson()`. +export type AnyInboundSettings = + | VlessInboundSettings + | VmessInboundSettings + | TrojanInboundSettings + | ShadowsocksInboundSettings + | HysteriaInboundSettings + | Hysteria2InboundSettings + | HttpInboundSettings + | MixedInboundSettings + | TunnelInboundSettings + | WireguardInboundSettings; + +export function createDefaultInboundSettings(protocol: string): AnyInboundSettings | null { + switch (protocol) { + case 'vless': return createDefaultVlessInboundSettings(); + case 'vmess': return createDefaultVmessInboundSettings(); + case 'trojan': return createDefaultTrojanInboundSettings(); + case 'shadowsocks': return createDefaultShadowsocksInboundSettings(); + case 'hysteria': return createDefaultHysteriaInboundSettings(); + case 'hysteria2': return createDefaultHysteria2InboundSettings(); + case 'http': return createDefaultHttpInboundSettings(); + case 'mixed': return createDefaultMixedInboundSettings(); + case 'tunnel': return createDefaultTunnelInboundSettings(); + case 'wireguard': return createDefaultWireguardInboundSettings(); + default: return null; + } +} diff --git a/frontend/src/pages/inbounds/InboundsPage.tsx b/frontend/src/pages/inbounds/InboundsPage.tsx index c72b078b..d08fa3ac 100644 --- a/frontend/src/pages/inbounds/InboundsPage.tsx +++ b/frontend/src/pages/inbounds/InboundsPage.tsx @@ -20,7 +20,7 @@ import { } from '@ant-design/icons'; import { HttpUtil, SizeFormatter, RandomUtil } from '@/utils'; -import { Inbound } from '@/models/inbound'; +import { createDefaultInboundSettings } from '@/lib/xray/inbound-defaults'; import { coerceInboundJsonField, type DBInbound } from '@/models/dbinbound'; import { useTheme } from '@/hooks/useTheme'; import { useMediaQuery } from '@/hooks/useMediaQuery'; @@ -354,7 +354,8 @@ export default function InboundsPage() { raw.clients = []; clonedSettings = JSON.stringify(raw); } catch { - clonedSettings = Inbound.Settings.getSettings(baseInbound.protocol).toString(); + const fallback = createDefaultInboundSettings(baseInbound.protocol); + clonedSettings = fallback ? JSON.stringify(fallback, null, 2) : '{}'; } const data = { up: 0,