import { AppNode, AppEdge, NodeData } from "../types/graph"; interface ValidationResult { isValid: boolean; errors: string[]; } /** * 生成WireGuard格式的配置文件 */ export function generateWireGuardConfig( node: AppNode, allNodes: AppNode[], allEdges: AppEdge[] ): string { const config: string[] = []; // [Interface] 部分 config.push('[Interface]'); config.push(`PrivateKey = ${node.data.privateKey}`); config.push(`Address = ${node.data.ipAddress}/32`); if (node.data.listenPort) { config.push(`ListenPort = ${node.data.listenPort}`); } if (node.data.dnsServers) { config.push(`DNS = ${node.data.dnsServers}`); } config.push(''); // 找到与该节点相连的所有节点 const connectedNodeIds = new Set(); allEdges.forEach(edge => { if (edge.source === node.id) { connectedNodeIds.add(edge.target); } if (edge.target === node.id) { connectedNodeIds.add(edge.source); } }); // 为每个连接的节点添加 [Peer] 部分 connectedNodeIds.forEach(peerId => { const peerNode = allNodes.find(n => n.id === peerId); if (peerNode && peerNode.data.publicKey && peerNode.data.ipAddress) { config.push('[Peer]'); config.push(`PublicKey = ${peerNode.data.publicKey}`); config.push(`AllowedIPs = ${peerNode.data.ipAddress}/32`); if (peerNode.data.endpoint) { config.push(`Endpoint = ${peerNode.data.endpoint}`); } if (peerNode.data.persistentKeepalive) { config.push(`PersistentKeepalive = ${peerNode.data.persistentKeepalive}`); } config.push(''); } }); return config.join('\n'); } /** * 生成所有节点的配置 */ export function generateAllConfigs( nodes: AppNode[], edges: AppEdge[] ): Record { const configs: Record = {}; nodes.forEach(node => { if (node.id && node.data.privateKey && node.data.ipAddress) { configs[node.id] = { name: node.data.label || node.id, config: generateWireGuardConfig(node, nodes, edges) }; } }); return configs; } /** * 下载配置文件 */ export function downloadConfig( nodeId: string, nodeName: string, configContent: string ): void { const element = document.createElement('a'); element.setAttribute( 'href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(configContent) ); element.setAttribute('download', `${nodeId}-${nodeName}.conf`); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } /** * 验证节点配置是否完整 */ export function validateNodeConfig(node: Partial): ValidationResult { const errors: string[] = []; if (!node.label || node.label.trim() === '') { errors.push('节点名称不能为空'); } if (!node.ipAddress || node.ipAddress.trim() === '') { errors.push('IP地址不能为空'); } else if (!isValidIP(node.ipAddress)) { errors.push('IP地址格式无效'); } if (!node.privateKey || node.privateKey.trim() === '') { errors.push('私钥不能为空'); } if (!node.publicKey || node.publicKey.trim() === '') { errors.push('公钥不能为空'); } return { isValid: errors.length === 0, errors }; } /** * 验证IP地址格式 */ function isValidIP(ip: string): boolean { const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; if (!ipv4Regex.test(ip)) { return false; } const parts = ip.split('.'); return parts.every(part => { const num = parseInt(part, 10); return num >= 0 && num <= 255; }); }