stream-defaults.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import {
  2. GrpcStreamSettingsSchema,
  3. HttpUpgradeStreamSettingsSchema,
  4. HysteriaStreamSettingsSchema,
  5. KcpStreamSettingsSchema,
  6. TcpStreamSettingsSchema,
  7. WsStreamSettingsSchema,
  8. XHttpStreamSettingsSchema,
  9. } from '@/schemas/protocols/stream';
  10. import {
  11. RealityStreamSettingsSchema,
  12. TlsStreamSettingsSchema,
  13. } from '@/schemas/protocols/security';
  14. const NETWORK_KEY_MAP = {
  15. tcp: 'tcpSettings',
  16. kcp: 'kcpSettings',
  17. ws: 'wsSettings',
  18. grpc: 'grpcSettings',
  19. httpupgrade: 'httpupgradeSettings',
  20. xhttp: 'xhttpSettings',
  21. hysteria: 'hysteriaSettings',
  22. } as const;
  23. type SchemaWithParse = { safeParse: (v: unknown) => { success: boolean; data?: unknown } };
  24. function parseOrDefault(schema: SchemaWithParse, value: unknown): unknown {
  25. const parsed = schema.safeParse(value ?? {});
  26. if (parsed.success) return parsed.data;
  27. const fallback = schema.safeParse({});
  28. return fallback.success ? fallback.data : value;
  29. }
  30. function networkSchemaFor(network: string): SchemaWithParse | null {
  31. switch (network) {
  32. case 'tcp': return TcpStreamSettingsSchema;
  33. case 'kcp': return KcpStreamSettingsSchema;
  34. case 'ws': return WsStreamSettingsSchema;
  35. case 'grpc': return GrpcStreamSettingsSchema;
  36. case 'httpupgrade': return HttpUpgradeStreamSettingsSchema;
  37. case 'xhttp': return XHttpStreamSettingsSchema;
  38. case 'hysteria': return HysteriaStreamSettingsSchema;
  39. default: return null;
  40. }
  41. }
  42. function securitySchemaFor(security: string): { key: string; schema: SchemaWithParse } | null {
  43. switch (security) {
  44. case 'tls': return { key: 'tlsSettings', schema: TlsStreamSettingsSchema };
  45. case 'reality': return { key: 'realitySettings', schema: RealityStreamSettingsSchema };
  46. default: return null;
  47. }
  48. }
  49. export function fillStreamDefaults(stream: Record<string, unknown>): Record<string, unknown> {
  50. const network = (stream.network as string | undefined) ?? 'tcp';
  51. const security = (stream.security as string | undefined) ?? 'none';
  52. const out: Record<string, unknown> = { ...stream, network, security };
  53. const subKey = NETWORK_KEY_MAP[network as keyof typeof NETWORK_KEY_MAP];
  54. const netSchema = networkSchemaFor(network);
  55. if (subKey && netSchema) {
  56. out[subKey] = parseOrDefault(netSchema, out[subKey]);
  57. }
  58. const sec = securitySchemaFor(security);
  59. if (sec) {
  60. out[sec.key] = parseOrDefault(sec.schema, out[sec.key]);
  61. }
  62. return out;
  63. }