UNPKG

wifi-radar

Version:

Comprehensive WiFi network analysis & performance testing tool for macOS - speed tests, latency analysis, health diagnostics, QoS analysis & more

213 lines β€’ 9.96 kB
import chalk from 'chalk'; export class TopologyMapper { generateTopology(networks, devices) { const currentNetwork = networks.find(n => n.isConnected); const relationships = this.generateRelationships(networks, devices); return { router: { mac: currentNetwork?.bssid || 'unknown', ip: '192.168.1.1', // Default assumption vendor: this.getRouterVendor(currentNetwork?.bssid), model: 'Unknown Router' }, devices, networks, relationships }; } renderTopologyASCII(topology) { const lines = []; // Header lines.push(chalk.cyan.bold('🌐 NETWORK TOPOLOGY MAP')); lines.push(chalk.gray('─'.repeat(50))); lines.push(''); // Router/Gateway const router = topology.router; lines.push(chalk.yellow.bold(`πŸ“‘ GATEWAY: ${router.vendor || 'Unknown'}`)); lines.push(chalk.gray(` MAC: ${router.mac}`)); lines.push(chalk.gray(` IP: ${router.ip}`)); lines.push(''); // Connected Network const connectedNet = topology.networks.find(n => n.isConnected); if (connectedNet) { lines.push(chalk.green.bold(`πŸ”— CONNECTED TO: ${connectedNet.ssid}`)); lines.push(chalk.gray(` Channel: ${connectedNet.channel} (${this.getFrequencyBand(connectedNet.frequency)})`)); lines.push(chalk.gray(` Signal: ${this.formatSignalStrength(connectedNet.signal)}`)); lines.push(chalk.gray(` Security: ${connectedNet.security.join(', ')}`)); lines.push(''); } // Device Tree lines.push(chalk.blue.bold('πŸ“± CONNECTED DEVICES')); lines.push(''); if (topology.devices.length === 0) { lines.push(chalk.gray(' No devices detected')); } else { topology.devices.forEach((device, index) => { const isLast = index === topology.devices.length - 1; const prefix = isLast ? '└── ' : 'β”œβ”€β”€ '; const deviceIcon = this.getDeviceIcon(device.deviceType); lines.push(chalk.white(`${prefix}${deviceIcon} ${device.hostname || 'Unknown Device'}`)); lines.push(chalk.gray(`β”‚ MAC: ${device.mac}`)); lines.push(chalk.gray(`β”‚ IP: ${device.ip || 'Unknown'}`)); lines.push(chalk.gray(`β”‚ Type: ${device.deviceType || 'unknown'}`)); if (device.vendor) { lines.push(chalk.gray(`β”‚ Vendor: ${device.vendor}`)); } if (!isLast) lines.push('β”‚'); }); } lines.push(''); // Nearby Networks const nearbyNetworks = topology.networks.filter(n => !n.isConnected); if (nearbyNetworks.length > 0) { lines.push(chalk.magenta.bold('πŸ“Ά NEARBY NETWORKS')); lines.push(''); nearbyNetworks .sort((a, b) => b.signal - a.signal) .slice(0, 10) // Top 10 networks .forEach(network => { const signalBars = this.getSignalBars(network.signal); const securityIcon = network.security.includes('Open') ? 'πŸ”“' : 'πŸ”’'; lines.push(chalk.white(`${signalBars} ${securityIcon} ${network.ssid}`)); lines.push(chalk.gray(` Channel ${network.channel} β€’ ${this.formatSignalStrength(network.signal)} β€’ ${network.security.join(', ')}`)); }); } return lines.join('\n'); } renderInteractiveMap(topology) { const lines = []; // ASCII Art Network Diagram lines.push(chalk.cyan.bold(' 🌐 INTERACTIVE NETWORK MAP')); lines.push(''); lines.push(' β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”'); lines.push(' β”‚ INTERNET β”‚'); lines.push(' β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜'); lines.push(' β”‚'); lines.push(' β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”'); lines.push(` β”‚ ${chalk.yellow('ROUTER')} β”‚`); lines.push(` β”‚ ${topology.router.vendor || 'Unknown'} β”‚`); lines.push(' β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜'); lines.push(' β”‚'); lines.push(' β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”'); lines.push(` β”‚ ${chalk.green('WiFi Network')} β”‚`); const connectedNet = topology.networks.find(n => n.isConnected); if (connectedNet) { lines.push(` β”‚ ${connectedNet.ssid.substring(0, 10)} β”‚`); } else { lines.push(' β”‚ Disconnected β”‚'); } lines.push(' β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜'); lines.push(' β”‚'); // Device connections if (topology.devices.length > 0) { const deviceCount = Math.min(topology.devices.length, 3); if (deviceCount === 1) { lines.push(' β”‚'); lines.push(' β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”'); lines.push(` β”‚ ${this.getDeviceIcon(topology.devices[0].deviceType)} Device 1 β”‚`); lines.push(' β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜'); } else { // Multiple devices in tree structure lines.push(' β”Œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”'); for (let i = 0; i < deviceCount; i++) { const device = topology.devices[i]; if (i === 0) { lines.push(` β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”‚ β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”`); lines.push(` β”‚ ${this.getDeviceIcon(device.deviceType)} Device ${i + 1} β”‚ β”‚ β”‚ ${this.getDeviceIcon(topology.devices[1]?.deviceType || 'unknown')} Device 2 β”‚`); lines.push(` β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜`); if (deviceCount > 2) { lines.push(' β”‚'); lines.push(` β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”`); lines.push(` β”‚ ${this.getDeviceIcon(topology.devices[2].deviceType)} Device 3 β”‚`); lines.push(' β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜'); } break; } } } } else { lines.push(' β”‚'); lines.push(' β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”'); lines.push(' β”‚ No Devicesβ”‚'); lines.push(' β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜'); } return lines.join('\n'); } generateRelationships(networks, devices) { const relationships = []; // Connect all devices to the router const connectedNetwork = networks.find(n => n.isConnected); if (connectedNetwork) { devices.forEach(device => { relationships.push({ from: connectedNetwork.bssid, to: device.mac, type: 'connected', strength: device.signal || 80 // Default strength }); }); } return relationships; } getRouterVendor(bssid) { if (!bssid) return undefined; const oui = bssid.substring(0, 8).toUpperCase(); const vendors = { '00:1B:63': 'Apple', '00:25:00': 'Apple', '3C:15:C2': 'Apple', '44:D9:E7': 'TP-Link', '98:DE:D0': 'Netgear', 'A0:63:91': 'Linksys' }; return vendors[oui]; } getDeviceIcon(deviceType) { const icons = { phone: 'πŸ“±', laptop: 'πŸ’»', tablet: 'πŸ“±', iot: '🏠', unknown: '❓' }; return icons[deviceType] || icons.unknown; } getSignalBars(signal) { if (signal >= -30) return chalk.green('β–°β–°β–°β–°β–°'); if (signal >= -50) return chalk.green('β–°β–°β–°β–°β–±'); if (signal >= -60) return chalk.yellow('β–°β–°β–°β–±β–±'); if (signal >= -70) return chalk.yellow('β–°β–°β–±β–±β–±'); if (signal >= -80) return chalk.red('β–°β–±β–±β–±β–±'); return chalk.red('β–±β–±β–±β–±β–±'); } formatSignalStrength(signal) { const strength = signal >= -50 ? 'Excellent' : signal >= -60 ? 'Good' : signal >= -70 ? 'Fair' : 'Poor'; const color = signal >= -50 ? chalk.green : signal >= -60 ? chalk.yellow : signal >= -70 ? chalk.yellow : chalk.red; return color(`${signal} dBm (${strength})`); } getFrequencyBand(frequency) { if (frequency >= 2400 && frequency <= 2500) return '2.4 GHz'; if (frequency >= 5000 && frequency <= 6000) return '5 GHz'; if (frequency >= 6000 && frequency <= 7000) return '6 GHz'; return 'Unknown'; } } //# sourceMappingURL=topology.js.map