import type { ParsedNode } from './ss.js'; import { readInsecure } from './util.js'; // TUIC v5: tuic://uuid:password@host:port?sni=...&alpn=h3&congestion_control=bbr&allow_insecure=1#name export function parseTuic(uri: string): ParsedNode { const url = new URL(uri); const server = url.hostname; const port = parseInt(url.port, 10); const name = decodeURIComponent(url.hash.slice(1)) || 'TUIC'; const uuid = decodeURIComponent(url.username); const password = decodeURIComponent(url.password); const params = url.searchParams; const alpn = params.get('alpn') || 'h3'; const sni = params.get('sni') || ''; // Surge uses the type name `tuic-v5` for TUIC v5 (uuid+password); plain `tuic` is v4 (token). // There is NO `version` field — using `tuic` + `version=5` makes Surge parse the line as v4 and // reject it ("token must be provided"). Field order mirrors Surge Mac 6.6.0's own GUI export. let line = `${name} = tuic-v5, ${server}, ${port}, password=${password}, uuid=${uuid}`; if (alpn) line += `, alpn=${alpn}`; line += `, skip-cert-verify=${readInsecure(params)}`; if (sni) line += `, sni=${sni}`; return { name, type: 'tuic', server, port, surgeLine: line }; }