const DEVICE_TO_NODE = { server: 'hw-dell-pe', switch: 'net-catalyst', storage: 'storage-netapp', firewall: 'net-fortinet', router: 'net-junper-srx', loadbalancer: 'net-f5', san: 'storage-pure', pdu: 'infra-pdu', ups: 'infra-apc-ups', cooling: 'infra-cooling', patch_panel: 'infra-patch-panel', tape: 'storage-netapp', kvm: 'infra-rack', other: 'infra-rack' }; const MANUFACTURER_NODE = { hpe: 'hw-hpe-dl', dell: 'hw-dell-pe', lenovo: 'hw-lenovo-ts', cisco: 'net-catalyst', juniper: 'net-junper-ex', arista: 'net-arista', netapp: 'storage-netapp', pure: 'storage-pure', fortinet: 'net-fortinet', f5: 'net-f5', palo: 'net-paloalto', nvidia: 'ai-nvidia', apc: 'infra-apc-ups' }; const DIAGRAM_TYPE_LABELS = { data_architecture: 'Data Architectuur', network_topology: 'Netwerk Topologie', system_architecture: 'Systeem Architectuur', application_flow: 'Applicatie Flow', application_landscape: 'Applicatie Landschap' }; function resolveNodeType(device) { const m = (device.manufacturer || '').toLowerCase(); for (const [key, type] of Object.entries(MANUFACTURER_NODE)) { if (m.includes(key)) return type; } return DEVICE_TO_NODE[device.device_type] || 'hw-dell-pe'; } function rackDevicesToNodes(devices, startX = 40, startY = 40) { return devices.map((d, i) => ({ id: 'rd-' + d.id, type: resolveNodeType(d), x: startX + (i % 4) * 180, y: startY + Math.floor(i / 4) * 90, label: d.name, sub: (d.model || d.device_type || '').toString(), css: 'node-hw', w: 160, h: 48, ip: d.mgmt_ip || '', vendor: d.manufacturer || '', model: d.model || '', specs: d.specs || '', notes: d.notes || '', rack_device_id: d.id, layer: 'infra' })); } function parseDiagramJson(diagram) { let nodes = []; let edges = []; try { nodes = JSON.parse(diagram.nodes || '[]'); edges = JSON.parse(diagram.edges || '[]'); } catch (e) { /* ignore */ } if (!Array.isArray(nodes) && nodes && nodes.nodes) { edges = nodes.edges || []; nodes = nodes.nodes || []; } if (!Array.isArray(edges) && edges && edges.edges) { nodes = edges.nodes || nodes; edges = edges.edges || []; } if (!Array.isArray(nodes)) nodes = []; if (!Array.isArray(edges)) edges = []; return { nodes, edges }; } function summarizeDiagram(diagram) { const { nodes, edges } = parseDiagramJson(diagram); const layers = {}; nodes.forEach(n => { const layer = n.layer || (n.type || '').split('-')[0] || 'other'; layers[layer] = (layers[layer] || 0) + 1; }); const protocols = {}; edges.forEach(e => { const p = e.protocol || 'unspecified'; protocols[p] = (protocols[p] || 0) + 1; }); return { nodes, edges, layers, protocols, nodeCount: nodes.length, edgeCount: edges.length }; } function getLayerForCategory(catLabel) { const c = (catLabel || '').toLowerCase(); if (c.includes('data bron') || c.includes('ingest') || c.includes('opslag') || c.includes('database')) return 'data'; if (c.includes('microservice') || c.includes('apps')) return 'app'; if (c.includes('api') || c.includes('messaging') || c.includes('queue')) return 'integration'; if (c.includes('netwerk') || c.includes('compute / server') || c.includes('infrastructure') || c.includes('security') || c.includes('observability') || c.includes('ci/cd')) return 'infra'; if (c.includes('ai')) return 'app'; return 'other'; } module.exports = { DEVICE_TO_NODE, DIAGRAM_TYPE_LABELS, resolveNodeType, rackDevicesToNodes, parseDiagramJson, summarizeDiagram, getLayerForCategory };