import { RandomUtil, Wireguard } from '@/utils'; import type { BlackholeOutboundSettings } from '@/schemas/protocols/outbound/blackhole'; import type { DNSOutboundSettings } from '@/schemas/protocols/outbound/dns'; import type { FreedomOutboundSettings } from '@/schemas/protocols/outbound/freedom'; import type { HttpOutboundSettings } from '@/schemas/protocols/outbound/http'; import type { HysteriaOutboundSettings } from '@/schemas/protocols/outbound/hysteria'; import type { LoopbackOutboundSettings } from '@/schemas/protocols/outbound/loopback'; import type { ShadowsocksOutboundSettings } from '@/schemas/protocols/outbound/shadowsocks'; import type { SocksOutboundSettings } from '@/schemas/protocols/outbound/socks'; import type { TrojanOutboundSettings } from '@/schemas/protocols/outbound/trojan'; import type { VlessOutboundSettings } from '@/schemas/protocols/outbound/vless'; import type { VmessOutboundSettings } from '@/schemas/protocols/outbound/vmess'; import type { WireguardOutboundSettings } from '@/schemas/protocols/outbound/wireguard'; // Plain-object factories mirroring `new Outbound.Settings()` from the // legacy class hierarchy, then `.toJson()`. The output matches the wire // shape — the same starting state the OutboundFormModal's `ob.settings` // holds the first time the user picks a protocol. // // Required-by-schema fields the legacy class leaves undefined (address, // port, user-supplied ids/passwords) become empty stubs here. Zod will // reject the default output until the user fills them in via the form; // this is intentional and matches the legacy "scaffold object" behavior. export function createDefaultFreedomOutboundSettings(): FreedomOutboundSettings { return {}; } export function createDefaultBlackholeOutboundSettings(): BlackholeOutboundSettings { return {}; } export function createDefaultLoopbackOutboundSettings(): LoopbackOutboundSettings { return { inboundTag: '' }; } export function createDefaultDNSOutboundSettings(): DNSOutboundSettings { return { rewriteNetwork: '', rewriteAddress: '', rewritePort: 53, userLevel: 0, rules: [], }; } export function createDefaultVmessOutboundSettings(): VmessOutboundSettings { return { vnext: [{ address: '', port: 443, users: [{ id: '', security: 'auto' }], }], }; } export function createDefaultVlessOutboundSettings(): VlessOutboundSettings { return { address: '', port: 443, id: '', flow: '', encryption: 'none', }; } export function createDefaultTrojanOutboundSettings(): TrojanOutboundSettings { return { servers: [{ address: '', port: 443, password: '' }], }; } // Why: legacy constructor leaves method undefined; the form's Select // snaps to the first option when the user opens it. We pick the same // modern default the inbound shadowsocks factory uses // (2022-blake3-aes-128-gcm) so the OutboundFormModal renders a coherent // initial state instead of an empty Select. export function createDefaultShadowsocksOutboundSettings(): ShadowsocksOutboundSettings { return { servers: [{ address: '', port: 443, password: '', method: '2022-blake3-aes-128-gcm', }], }; } export function createDefaultSocksOutboundSettings(): SocksOutboundSettings { return { servers: [{ address: '', port: 1080, users: [] }], }; } export function createDefaultHttpOutboundSettings(): HttpOutboundSettings { return { servers: [{ address: '', port: 8080, users: [] }], }; } interface WireguardOutboundSeed { secretKey?: string; } export function createDefaultWireguardOutboundSettings( seed: WireguardOutboundSeed = {}, ): WireguardOutboundSettings { const secretKey = seed.secretKey ?? Wireguard.generateKeypair().privateKey; return { mtu: 1420, secretKey, address: [], peers: [{ publicKey: '', allowedIPs: ['0.0.0.0/0', '::/0'], endpoint: '', }], noKernelTun: false, }; } export function createDefaultHysteriaOutboundSettings(): HysteriaOutboundSettings { return { address: '', port: 443, version: 2 }; } export type AnyOutboundSettings = | BlackholeOutboundSettings | DNSOutboundSettings | FreedomOutboundSettings | HttpOutboundSettings | HysteriaOutboundSettings | LoopbackOutboundSettings | ShadowsocksOutboundSettings | SocksOutboundSettings | TrojanOutboundSettings | VlessOutboundSettings | VmessOutboundSettings | WireguardOutboundSettings; // Protocol-aware dispatch. Mirrors the legacy // `Outbound.Settings.getSettings(protocol)` switch. Note: the inbound // dispatcher returns `null` for unknown protocols and so does this one, // keeping the contract identical so callers can stay protocol-agnostic. // // The `RandomUtil` reference is held to silence unused-import warnings // when no per-call randomization happens at the dispatcher level — // individual factories may pull from it via their own seeds. export function createDefaultOutboundSettings(protocol: string): AnyOutboundSettings | null { void RandomUtil; switch (protocol) { case 'freedom': return createDefaultFreedomOutboundSettings(); case 'blackhole': return createDefaultBlackholeOutboundSettings(); case 'dns': return createDefaultDNSOutboundSettings(); case 'vmess': return createDefaultVmessOutboundSettings(); case 'vless': return createDefaultVlessOutboundSettings(); case 'trojan': return createDefaultTrojanOutboundSettings(); case 'shadowsocks': return createDefaultShadowsocksOutboundSettings(); case 'socks': return createDefaultSocksOutboundSettings(); case 'http': return createDefaultHttpOutboundSettings(); case 'wireguard': return createDefaultWireguardOutboundSettings(); case 'hysteria': return createDefaultHysteriaOutboundSettings(); case 'loopback': return createDefaultLoopbackOutboundSettings(); default: return null; } }