Quellcode durchsuchen

refactor(frontend): lift Protocols + TLS_FLOW_CONTROL consts to schemas/primitives

Step 4b. The Protocols and TLS_FLOW_CONTROL enums on models/inbound.ts
were dragging five page files into that 3,300-line module just to read
literal string constants. Lifting them to schemas/primitives lets those
pages drop the @/models/inbound import entirely.

  - schemas/primitives/protocol.ts now exports a Protocols const map
    alongside the existing ProtocolSchema. TUN stays in the const for
    parity (legacy panel deployments may have saved TUN inbounds) even
    though the Go validator no longer accepts it as a new write.
  - schemas/primitives/flow.ts now exports TLS_FLOW_CONTROL. The
    empty-string default isn't keyed because the legacy never had a
    NONE entry — call sites compare against the two real flow values.

Updated five consumers:
  - useInbounds.ts: TRACKED_PROTOCOLS now annotated readonly string[]
    so .includes(string) keeps narrowing through the array literal
  - QrCodeModal.tsx, InboundInfoModal.tsx: Protocols
  - ClientFormModal.tsx, ClientBulkAddModal.tsx: TLS_FLOW_CONTROL

Suite: 89 tests across 8 files; typecheck + lint clean.

models/inbound.ts is now imported by:
  - InboundFormModal.tsx (heavy use of Inbound class + getSettings)
  - test/inbound-link.test.ts + test/shadow.test.ts + test/headers.test.ts
    (intentional — these are parity tests against the legacy class)

OutboundFormModal still imports from models/outbound. Both form modals
are the multi-day Pattern A rewrites the plan scopes separately.
MHSanaei vor 21 Stunden
Ursprung
Commit
4ce2503c1e

+ 1 - 1
frontend/src/pages/clients/ClientBulkAddModal.tsx

@@ -6,7 +6,7 @@ import dayjs from 'dayjs';
 import type { Dayjs } from 'dayjs';
 
 import { HttpUtil, RandomUtil, SizeFormatter } from '@/utils';
-import { TLS_FLOW_CONTROL } from '@/models/inbound';
+import { TLS_FLOW_CONTROL } from '@/schemas/primitives';
 import DateTimePicker from '@/components/DateTimePicker';
 import type { InboundOption } from '@/hooks/useClients';
 import { ClientBulkAddFormSchema, type ClientBulkAddFormValues } from '@/schemas/client';

+ 1 - 1
frontend/src/pages/clients/ClientFormModal.tsx

@@ -19,7 +19,7 @@ import type { Dayjs } from 'dayjs';
 
 import { HttpUtil, RandomUtil } from '@/utils';
 import DateTimePicker from '@/components/DateTimePicker';
-import { TLS_FLOW_CONTROL } from '@/models/inbound';
+import { TLS_FLOW_CONTROL } from '@/schemas/primitives';
 import type { ClientRecord, InboundOption } from '@/hooks/useClients';
 import { ClientFormSchema, ClientCreateFormSchema } from '@/schemas/client';
 import './ClientFormModal.css';

+ 1 - 1
frontend/src/pages/inbounds/InboundInfoModal.tsx

@@ -12,7 +12,7 @@ import {
   ClipboardManager,
   FileManager,
 } from '@/utils';
-import { Protocols } from '@/models/inbound';
+import { Protocols } from '@/schemas/primitives';
 import InfinityIcon from '@/components/InfinityIcon';
 import { useDatepicker } from '@/hooks/useDatepicker';
 import type { SubSettings } from './useInbounds';

+ 1 - 1
frontend/src/pages/inbounds/QrCodeModal.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
 import { Collapse, Modal } from 'antd';
 import type { CollapseProps } from 'antd';
 
-import { Protocols } from '@/models/inbound';
+import { Protocols } from '@/schemas/primitives';
 import QrPanel from './QrPanel';
 import type { SubSettings } from './useInbounds';
 

+ 2 - 2
frontend/src/pages/inbounds/useInbounds.ts

@@ -4,7 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
 import { HttpUtil } from '@/utils';
 import { parseMsg } from '@/utils/zodValidate';
 import { DBInbound } from '@/models/dbinbound';
-import { Protocols } from '@/models/inbound';
+import { Protocols } from '@/schemas/primitives';
 import { setDatepicker } from '@/hooks/useDatepicker';
 import { keys } from '@/api/queryKeys';
 import { SlimInboundListSchema, LastOnlineMapSchema, InboundDetailSchema } from '@/schemas/inbound';
@@ -31,7 +31,7 @@ interface ClientRollup {
   comments: Map<string, string>;
 }
 
-const TRACKED_PROTOCOLS = [
+const TRACKED_PROTOCOLS: readonly string[] = [
   Protocols.VMESS,
   Protocols.VLESS,
   Protocols.TROJAN,

+ 8 - 0
frontend/src/schemas/primitives/flow.ts

@@ -6,3 +6,11 @@ export const FlowSchema = z.enum([
   'xtls-rprx-vision-udp443',
 ]);
 export type Flow = z.infer<typeof FlowSchema>;
+
+// Const map matching the legacy models/inbound.ts `TLS_FLOW_CONTROL`
+// export. The empty-string default isn't keyed here — the legacy never
+// carried a NONE key and call sites compare against the two real flows.
+export const TLS_FLOW_CONTROL = Object.freeze({
+  VISION: 'xtls-rprx-vision',
+  VISION_UDP443: 'xtls-rprx-vision-udp443',
+}) satisfies Record<string, Exclude<Flow, ''>>;

+ 20 - 0
frontend/src/schemas/primitives/protocol.ts

@@ -13,3 +13,23 @@ export const ProtocolSchema = z.enum([
   'tunnel',
 ]);
 export type Protocol = z.infer<typeof ProtocolSchema>;
+
+// Const map matching the legacy models/inbound.ts `Protocols` export so
+// call sites can swap the import without touching `Protocols.VLESS`-style
+// references throughout the codebase. Frozen so downstream code can't
+// mutate the dispatch table. TUN is kept here for parity even though the
+// Go backend's validator no longer accepts it — existing panel deployments
+// may still have TUN inbounds saved that we want to render.
+export const Protocols = Object.freeze({
+  VMESS: 'vmess',
+  VLESS: 'vless',
+  TROJAN: 'trojan',
+  SHADOWSOCKS: 'shadowsocks',
+  WIREGUARD: 'wireguard',
+  HYSTERIA: 'hysteria',
+  HYSTERIA2: 'hysteria2',
+  HTTP: 'http',
+  MIXED: 'mixed',
+  TUNNEL: 'tunnel',
+  TUN: 'tun',
+});