Full health check: fix startup crash, add subnet input to network discovery
Server fixes: - database.js: auto-create data/ directory on startup — was crashing on fresh clone because the gitignored directory didn't exist - better-sqlite3 upgraded to latest (13.x) for Node 26 compatibility Network discovery: - discoverNetwork() accepts optional subnet param; scans that range instead of auto-detecting when provided - New GET /api/network-subnets endpoint returns detected local interfaces so UI can offer quick-select buttons - Discovery modal: subnet text input + Scan button + auto-detect quick-select; local subnet buttons populate once the modal is open - server/index.js: pass subnet from request body to discoverNetwork() Infra: - React client runs on PORT=3456 in dev to avoid port conflicts - .claude/launch.json added for one-command preview via Express (serves the pre-built client, no port conflict with the preview tool) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
59078362da
commit
f119168399
14 files changed
+119
-427
No files matched your search
@@ -101,20 +101,29 @@ async function getArpHosts() {
|
||||
});
|
||||
}
|
||||
|
||||
async function discoverNetwork() {
|
||||
const subnets = getLocalSubnets();
|
||||
async function discoverNetwork(customSubnet = null) {
|
||||
const arpHosts = await getArpHosts();
|
||||
const arpIps = new Set(arpHosts.map(h => h.ip));
|
||||
|
||||
// Collect all IPs to scan: ARP table + subnet range
|
||||
const allIps = new Map();
|
||||
for (const h of arpHosts) allIps.set(h.ip, { ip: h.ip, hostname: h.hostname });
|
||||
|
||||
for (const subnet of subnets) {
|
||||
if (!subnet.prefix) continue;
|
||||
const range = subnetToRange(subnet.prefix);
|
||||
for (const ip of range) {
|
||||
if (!allIps.has(ip)) allIps.set(ip, { ip, hostname: null });
|
||||
if (customSubnet) {
|
||||
// Scan the user-specified subnet only (no ARP seeding, still probe all IPs in range)
|
||||
const range = subnetToRange(customSubnet);
|
||||
for (const ip of range) allIps.set(ip, { ip, hostname: null });
|
||||
// Supplement with ARP hostnames for any IPs that happen to be in the ARP table
|
||||
for (const h of arpHosts) {
|
||||
if (allIps.has(h.ip) && h.hostname) allIps.get(h.ip).hostname = h.hostname;
|
||||
}
|
||||
} else {
|
||||
// Auto-detect: ARP table + all local subnets
|
||||
for (const h of arpHosts) allIps.set(h.ip, { ip: h.ip, hostname: h.hostname });
|
||||
for (const subnet of getLocalSubnets()) {
|
||||
if (!subnet.prefix) continue;
|
||||
const range = subnetToRange(subnet.prefix);
|
||||
for (const ip of range) {
|
||||
if (!allIps.has(ip)) allIps.set(ip, { ip, hostname: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user